http://poj.org/problem?id=1637
题意:
给出n个点和m条边,这些边有些是单向边,有些是双向边,判断是否能构成欧拉回路。
思路:
构成有向图欧拉回路的要求是入度=出度,无向图的要求是所有顶点的度数为偶数。
但不管是那个,顶点的度数若是奇数,那都是不能构成的。
这道题目是非常典型的混合图欧拉回路问题,对于双向边,我们先随便定个向,然后就这样先记录好每个顶点的入度和出度。
如果有顶点的度数为奇数,可以直接得出结论,是不能构成欧拉回路的。
那么,如果都是偶数呢?
因为还会存在入度不等于出度的情况,那么这个时候就要通过改变改变双向边的方向来改变度数。对于每个顶点,如果出度大于入度,那么就将该点与源点相连,容量为(out-in)/2,代表需要改变几条双向边的方向,同理,如果入度大于出度,那么就将该点与汇点相连,容量为(in-out)/2。
那么,顶点之间如何连接呢?
对于双向边,将该两个顶点相连,容量为1,代表这条边可以反向一次。
最后,走一遍最大流,如果满流,就说明能够构成欧拉回路。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 using namespace std; 11 typedef long long LL; 12 typedef pair<int,int> pll; 13 const int INF=0x3f3f3f3f; 14 const int maxn=1000+5; 15 16 struct Edge 17 { 18 int from,to,cap,flow; 19 Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){} 20 }; 21 22 struct Dinic 23 { 24 int n,m,s,t; 25 vector<Edge> edges; 26 vector<int> G[maxn]; 27 bool vis[maxn]; 28 int cur[maxn]; 29 int d[maxn]; 30 31 void init(int n) 32 { 33 this->n=n; 34 for(int i=0;i<n;++i) G[i].clear(); 35 edges.clear(); 36 } 37 38 void AddEdge(int from,int to,int cap) 39 { 40 edges.push_back( Edge(from,to,cap,0) ); 41 edges.push_back( Edge(to,from,0,0) ); 42 m=edges.size(); 43 G[from].push_back(m-2); 44 G[to].push_back(m-1); 45 } 46 47 bool BFS() 48 { 49 queue<int> Q; 50 memset(vis,0,sizeof(vis)); 51 vis[s]=true; 52 d[s]=0; 53 Q.push(s); 54 while(!Q.empty()) 55 { 56 int x=Q.front(); Q.pop(); 57 for(int i=0;i<G[x].size();++i) 58 { 59 Edge& e=edges[G[x][i]]; 60 if(!vis[e.to] && e.cap>e.flow) 61 { 62 vis[e.to]=true; 63 d[e.to]=d[x]+1; 64 Q.push(e.to); 65 } 66 } 67 } 68 return vis[t]; 69 } 70 71 int DFS(int x,int a) 72 { 73 if(x==t || a==0) return a; 74 int flow=0, f; 75 for(int &i=cur[x];i<G[x].size();++i) 76 { 77 Edge &e=edges[G[x][i]]; 78 if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0) 79 { 80 e.flow +=f; 81 edges[G[x][i]^1].flow -=f; 82 flow +=f; 83 a -=f; 84 if(a==0) break; 85 } 86 } 87 return flow; 88 } 89 90 int Maxflow(int s,int t) 91 { 92 this->s=s; this->t=t; 93 int flow=0; 94 while(BFS()) 95 { 96 memset(cur,0,sizeof(cur)); 97 flow +=DFS(s,INF); 98 } 99 return flow; 100 } 101 }DC; 102 103 int in[maxn],out[maxn]; 104 int u[maxn],v[maxn],w[maxn]; 105 int n,m; 106 107 int main() 108 { 109 //freopen("D:\input.txt","r",stdin); 110 int T; 111 scanf("%d",&T); 112 while(T--) 113 { 114 scanf("%d%d",&n,&m); 115 memset(in,0,sizeof(in)); 116 memset(out,0,sizeof(out)); 117 int src=0,dst=n+1; 118 DC.init(dst+1); 119 120 for(int i=1;i<=m;i++) 121 { 122 scanf("%d%d%d",&u[i],&v[i],&w[i]); 123 out[u[i]]++; 124 in[v[i]]++; 125 } 126 127 bool flag=true; 128 int full_flow=0; 129 for(int i=1;i<=n;i++) 130 { 131 if(((in[i]+out[i])&1)) {flag=false;break;} 132 if(in[i]>out[i]) {DC.AddEdge(i,dst,(in[i]-out[i])/2);full_flow+=(in[i]-out[i])/2;} 133 if(out[i]>in[i]) DC.AddEdge(src,i,(out[i]-in[i])/2); 134 } 135 136 if(flag) 137 { 138 for(int i=1;i<=m;i++) 139 if(!w[i]) DC.AddEdge(u[i],v[i],1); 140 } 141 142 if(flag) 143 { 144 int flow=DC.Maxflow(src,dst); 145 if(flow==full_flow) puts("possible"); 146 else puts("impossible"); 147 } 148 else puts("impossible"); 149 } 150 return 0; 151 }