大意 混合图中找欧拉回路
思路 混合图中判断是否存在欧拉回路的方法都是一样,只是如何去找欧拉回路的问题。
如何去找欧拉回路,满流后,如果图中已给出的无向边(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;
}
477

被折叠的 条评论
为什么被折叠?



