poj 1637 Sightseeing tour
题意:混合图求欧拉回路。
解法:对于欧拉图,所有顶点入度和出度之差均为偶数。
建图思路:1.首先为无向边随意定一个方向,统计每个点入度出度;
2.另设源点汇点,对于出度>入度的点,与源点连边,正向边容量为(out-in)/2,对于入度>出度的点,与汇点连边,正向边容量为(in-out)/2;
3.对于除了源点汇点之外的点,有向边舍弃,无向边按照先前指定的方向建边,容量为1.
整个图建好之后,流经每个顶点的容量可以理解成把这个点的入(出)边变成出(入)边的数量。。。
如果是满流就表示所有的点最后都能使得入度==出度。。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #define N 1010 6 #define M 10010 7 using namespace std; 8 const int inf=(1<<30); 9 struct Edge{ 10 int u,v,c,next; 11 }edge[M]; 12 int queue[N],stack[N],dis[N],head[N]; 13 int in[N],out[N]; 14 int cnt; 15 void init(){ 16 memset(head,-1,sizeof(head)); 17 memset(in,0,sizeof(in)); 18 memset(out,0,sizeof(out)); 19 cnt=0; 20 } 21 void add(int u,int v,int c){ 22 edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c; 23 edge[cnt].next=head[u];head[u]=cnt++; 24 } 25 int dinic(int s,int t){ 26 int ans=0; 27 while(1){ 28 int l,r,now,u,v,top; 29 memset(dis,-1,sizeof(dis)); 30 l=r=0; 31 queue[r++]=s; 32 dis[s]=0; 33 while(l<r){ 34 u=queue[l++]; 35 for(int k=head[u];k!=-1;k=edge[k].next){ 36 u=edge[k].u; 37 v=edge[k].v; 38 if(edge[k].c>0&&dis[v]==-1){ 39 dis[v]=dis[u]+1; 40 queue[r++]=v; 41 if(v==t){ 42 l=r; 43 break; 44 } 45 } 46 } 47 } 48 if(dis[t]==-1)break; 49 now=s; 50 top=0; 51 while(1){ 52 if(now!=t){ 53 int k; 54 for(k=head[now];k!=-1;k=edge[k].next){ 55 if(edge[k].c>0&&dis[edge[k].v]==dis[edge[k].u]+1)break; 56 } 57 if(k!=-1){ 58 stack[top++]=k; 59 now=edge[k].v; 60 } 61 else{ 62 if(top==0)break; 63 dis[edge[stack[--top]].v]=-1; 64 now=edge[stack[top]].u; 65 } 66 } 67 else{ 68 int flow=inf,w; 69 for(int i=0;i<top;i++){ 70 if(flow>edge[stack[i]].c){ 71 flow=edge[stack[i]].c; 72 w=i; 73 } 74 } 75 ans+=flow; 76 for(int i=0;i<top;i++){ 77 edge[stack[i]].c-=flow; 78 edge[stack[i]^1].c+=flow; 79 } 80 now=edge[stack[w]].u; 81 top=w; 82 } 83 } 84 } 85 return ans; 86 } 87 int abs(int a,int b){ 88 return a>b?(a-b):(b-a); 89 } 90 int main(){ 91 int n,m,t; 92 cin>>t; 93 while(t--){ 94 cin>>n>>m; 95 init(); 96 for(int i=1;i<=m;i++){ 97 int a,b,c; 98 cin>>a>>b>>c; 99 if(a==b)continue; 100 if(c==0){ 101 add(a,b,1); 102 add(b,a,0); 103 } 104 in[b]++; 105 out[a]++; 106 } 107 bool flag=0; 108 for(int i=1;i<=n;i++){ 109 if(abs(in[i]-out[i])&1){ 110 flag=1; 111 break; 112 } 113 } 114 if(flag){ 115 cout<<"impossible"<<endl; 116 continue; 117 } 118 int sum=0; 119 for(int i=1;i<=n;i++){ 120 if(out[i]>in[i]){ 121 add(0,i,(out[i]-in[i])/2); 122 add(i,0,0); 123 sum+=(out[i]-in[i])/2; 124 } 125 else{ 126 add(i,n+1,(in[i]-out[i])/2); 127 add(n+1,i,0); 128 } 129 } 130 int ans=dinic(0,n+1); 131 if(ans==sum) 132 cout<<"possible"<<endl; 133 else 134 cout<<"impossible"<<endl; 135 } 136 return 0; 137 }