现在的位置: 首页 > 综合 > 正文

UVA 10735 Euler Circuit

2019年04月05日 ⁄ 综合 ⁄ 共 3511字 ⁄ 字号 评论关闭

大意 混合图中找欧拉回路

思路 混合图中判断是否存在欧拉回路的方法都是一样,只是如何去找欧拉回路的问题。

如何去找欧拉回路,满流后,如果图中已给出的无向边(e.cap > 0)有流流过,则把该边反向,如果没有,则不改,然后用套圈算法去找欧拉回路。

/*UVA 10735*/
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <map>
using namespace std;

const int maxn = 110;
const int maxm = 110*110;
const int INF = 0x3f3f3f3f;

struct Edge
{
	int from, to, cap, flow;
	Edge(int from, int to, int cap, int flow): from(from), to(to), cap(cap), flow(flow) {}
};

struct Dinic
{
	int n, m, s, t;
	vector<Edge> edges;
	vector<int> G[maxn];
	bool vis[maxn];
	int d[maxn];
	int cur[maxn];
	
	void init(int n)
	{
		this->n = n;
		for(int i = 0; i <= n; i++) G[i].clear();
		edges.clear();
	}
	
	void ClearFlow ()
	{
		for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
	}
	
	void AddEdge(int from, int to, int cap)
	{
		edges.push_back(Edge (from, to, cap, 0));
		edges.push_back(Edge (to, from, 0, 0));
		m = edges.size();
		G[from].push_back(m-2);
		G[to].push_back(m-1);
	}
	
	bool BFS()
	{
		memset(vis, 0, sizeof(vis));
		queue<int> Q;
		Q.push(s);
		d[s] = 0;
		vis[s] = 1;
		while(!Q.empty())
		{
			int x = Q.front(); Q.pop();
			for(int i = 0; i < G[x].size(); i++)
			{
				Edge& e = edges[G[x][i]];
				if(!vis[e.to] && e.cap > e.flow)
				{
					vis[e.to] = 1;
					d[e.to] = d[x]+1;
					Q.push(e.to);
				}
			}
		}
		return vis[t];
	}
	
	int DFS(int x, int a)
	{
		if(x == t || a == 0) return a;
		int flow = 0, f;
		for(int &i = cur[x]; i < G[x].size(); i++)
		{
			Edge& e = edges[G[x][i]];
			if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0)
			{
				e.flow += f;
				edges[G[x][i]^1].flow -= f;
				flow += f;
				a -= f;
				if(a == 0) break;
			}
		}
		return flow;
	}
	
	int Maxflow(int s, int t)
	{
		this->s = s; this->t = t;
		int flow = 0;
		while(BFS())
		{
			memset(cur, 0, sizeof(cur));
			flow += DFS(s, INF);
		}
		return flow;
	}
};

void readint(int &x)
{
    char c;
    while(!isdigit(c)) c = getchar();
    
    x = 0;
    while(isdigit(c))
    {
        x = x*10 + c-'0';
        c = getchar();
    }
}

void writeint(int x)
{
    if(x > 9) writeint(x/10);
    putchar(x%10+'0');
}

int fa[maxn];
int find(int x) { return x == fa[x]? x : fa[x] = find(fa[x]); }
void Union(int x, int y) {x = find(x), y = find(y); if(x != y) fa[x] = y; }

//////////////////////
Dinic solver;
int n, m, s, t;

int ind[maxn], outd[maxn];
bool vis[maxn];

struct Edge2
{
	int v;
	bool vis;
	int next;
}edge[maxm];

int cnt;
int first[maxn];

void read_graph(int u, int v)
{
	edge[cnt].v = v, edge[cnt].vis = 0;
	edge[cnt].next = first[u], first[u] = cnt++;
}

void init()
{
	cnt = 0;
	memset(first, -1, sizeof(first));
	memset(ind, 0, sizeof(ind));
	memset(outd, 0, sizeof(outd));
	memset(vis, 0, sizeof(vis));
	for(int i = 0; i <= n+2; i++) fa[i] = i;
}

void read_case()
{
	readint(n), readint(m);
	
	init();
	solver.init(n+5);
	
	while(m--)
	{
		int x, y; char c;
		scanf("%d %d %c", &x, &y, &c);
		if(c == 'D') read_graph(x, y);
		else if(c == 'U') solver.AddEdge(x, y, 1);
		vis[x] = vis[y] = 1;
		outd[x]++, ind[y]++;
		Union(x, y);
	}
}

int totflow;

int build()
{
	s = 0, t = n+1;
	totflow = 0;
	for(int i = 1; i <= n; i++) if(vis[i])
	{
		if((outd[i]+ind[i]) & 1) return 0;
		else if(outd[i] > ind[i])
		{
			int d = outd[i]-ind[i];
			solver.AddEdge(s, i, d/2);
			totflow += d/2;
		}
		else if(ind[i] > outd[i])
		{
			int d = ind[i]-outd[i];
			solver.AddEdge(i, t, d/2);
		}
	}
	return 1;
}

int check()
{
	int count = 0;
	for(int i = 1; i <= n; i++) if(vis[i] && fa[i] == i) count++;
	if(count > 1) return 0;
	
	int ans = solver.Maxflow(s, t);
	if(ans >= totflow) return 1;
	return 0;
}

vector<int> ans;

int Euler(int u) //套圈算法 
{
	for(int e = first[u]; e != -1; e = edge[e].next)
	{
		if(edge[e].vis) continue;
		edge[e].vis = 1;
		Euler(edge[e].v);
		ans.push_back(edge[e].v);
	}
}

void rebuild()
{
	for(int i = 0; i < solver.edges.size(); i++)
	{
		Edge &e = solver.edges[i];
		if(e.cap > 0 && e.from >= 1 && e.from <= n) //已存在的边,e.cap > 0
		{
			if(e.flow == 0) read_graph(e.from, e.to);
			else read_graph(e.to, e.from);
		}
	}
}

void output()
{
	ans.clear();
	Euler(1);
	printf("1");
	for(int i = ans.size()-1; i >= 0; i--) printf(" %d", ans[i]);
	printf("\n");
}

void solve()
{
	read_case();
	if(build())
	{
		if(!check()) printf("No euler circuit exist\n");
		else
		{
			rebuild();
			output();
		}
	}
	else printf("No euler circuit exist\n");
}

int main()
{
	int T, times = 0;;
	for(readint(T); T > 0; T--)
	{
		if(times++) printf("\n");
		solve();
	}
	return 0;
}

抱歉!评论已关闭.