混合图偶拉回路的判定。
题意: 给出一张图,途中既有有向边又有无向边,现在想要判断这个图里边是否存在欧拉回路。
思路: 开始的时候我直接用求普通图的欧拉回路的方法求,如果求出的边的条数为m那么就存在,否则不存在。但是wa了。
如果存在欧拉回路,那么每个点的入度和出度相等。 我们要努力的做的是让每个点的出度和入度相等。
假设入度为in, 总度数为d,如果d为奇数, 那么可定不存在欧拉回路。 如果in>d/2也不存在欧拉回路。
我们努力做的就是构造d/2-in个入度, 这里我们用网络流。 对于每个无向边,我们缩成一个点,这个点向这条边两端的点有边,且流量为1, 源点到缩点也有边,流量为1. 途中原先的点向汇点的流量为d/2-in.如果这个图能满流,那么就存在欧拉回路。否则不存在。
AC代码:
View Code
#include <iostream> #include <cstdio> #include <string> #include <cstring> using namespace std; const int N = 8010, INF = 1<<29; struct EDGE { int u, v, next, cap; }edge[N*4]; int f[N], in[N], d[N], cur[N], dis[N], pre[N], gap[N], n, m; int num, head[N], cc; void add(int u, int v, int w) { edge[num].u = u; edge[num].v = v; edge[num].cap = w; edge[num].next = head[u]; head[u] = num++; } int find(int u) { if(f[u] != u) f[u] = find(f[u]); return f[u]; } void unio(int u, int v) { int x = find(u), y =find(v); if(x < y) f[y] = x; else f[x] = y; } bool init() { scanf("%d%d", &n, &m); int u, v, s, tp=n; cc = 0; num = 0; memset(head, -1, sizeof(head)); for(int i=1; i<=n; i++) { in[i] = d[i] = 0; f[i] = i; } for(int i=1; i<=m; i++) { scanf("%d%d%d", &u, &v, &s); unio(u, v); d[u]++; d[v]++; if(s == 1) { in[v]++; } else { tp++; cc++; add(tp,u,1); add(u,tp,0); add(tp,v,1); add(v,tp,0); add(0,tp,1); add(tp,0,0); } } bool flag = 1; for(int i=1; i<=n; i++) { if(d[i]%2 || (in[i] > d[i]/2)) { flag = 0; break; } /* if(i > 1) { if(f[i] != f[i-1]) { flag = 0; break; } }*/ add(i,tp+1,d[i]/2 - in[i]); add(tp+1, i, 0); } n = tp+1; if(!flag) { printf("impossible\n"); } return flag; } void solve(int s, int t) { memset(gap,0,sizeof(gap)); memset(dis,0,sizeof(dis)); int i; for(i=0;i<=t+1;i++) { cur[i] = head[i]; } int top=s; gap[s]=t+1; int maxflow=0,flow=INF; while(dis[s] < t+1) { for(i=cur[top];i != -1;i = edge[i].next) { if(edge[i].cap > 0 && dis[top] == dis[edge[i].v] + 1) break; } if(i != -1) { cur[top] = i; int v = edge[i].v; if(edge[i].cap < flow) { flow = edge[i].cap; } top = v; pre[v] = i; if(top == t) { maxflow += flow; while(top != s) { edge[pre[top]].cap -= flow; edge[pre[top]^1].cap += flow; top = edge[pre[top]^1].v; } flow = INF; } } else { if(--gap[dis[top]] == 0) { break; } dis[top] = t+1; cur[top] = head[top]; for(int j=head[top];j != -1;j=edge[j].next) { if(edge[j].cap > 0 && dis[edge[j].v] + 1 < dis[top]) { dis[top] = dis[edge[j].v] + 1; cur[top] = j; } } gap[dis[top]]++; if(top != s) { top = edge[pre[top]^1].v; } } } // cout<<maxflow<<" "<<cc<<endl; if(maxflow == cc) { printf("possible\n"); } else { printf("impossible\n"); } } int main() { int t; scanf("%d", &t); while(t--) { if(init()) { solve(0, n); } } return 0; }


浙公网安备 33010602011771号