POJ 1637 Sightseeing tour 建图+网络流
题意:
给定一个混合图,所谓混合图就是图中既有单向边也有双向边,现在求这样的图是否存在欧拉回路。
分析:
存在欧拉回路的有向图,必须满足[入度==出度],现在,有些边已经被定向,所以我们直接记录度数即可,对于无向边呢?
对于这样的边,我们只需要先随便定向,然后记录出入度。(这些边只用来计算出入度,不用于网络流建图)
然后我们开始建图。现在极有可能有些点是不满足[入度==出度]的,所以我们要通过一些变向操作,使得图中所有点满足判定。
如果一个点入度和出度的奇偶性不同,那整张图一定是不合法的。因为改变一条边的方向对端点的入度和出度是同时影响的,且是反向的,比如入度加一出度减一,或者出度加一入度减一,因此无论如何,那样的点都不可能满足判定条件的;
随后,我们对于:
所有入度>出度的点,从超级源点连一条容量为(入度-出度)/2的边;
所有出度>入度的点,向超级汇点连一条容量为(出度-入度)/2的边;
这样,一单位流量的需求,意味着有这么多边需要变向来使图满足判定条件。所以那些边可以变向,我们就使它的贡献为1 。
所以,对于我们曾随便定向的那些无向边,我们在网络流建图中,向它们相反方向建一条流量为1的边(与我们随便定的向相反)。
之后检验整张图与源点汇点连得边是否满流,满流则possible,不满则impossible。
代码:
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<queue> 7 #define ms(a,x) memset(a,x,sizeof(a)) 8 using namespace std; 9 const int inf=0x3f3f3f3f; 10 const int N=1005; 11 struct edge{int x,y,d;}w[N]; 12 struct node{int y,z,nxt;}e[N*2]; 13 int in[N],ot[N],S,T,q[N],h[N],c=1; 14 int n,m,sm=0,tot=0,d[N],k,cas,flg; 15 void add(int x,int y,int z){ 16 e[++c]=(node){y,z,h[x]};h[x]=c; 17 e[++c]=(node){x,0,h[y]};h[y]=c; 18 } bool bfs(){ 19 int f=1,t=0;ms(d,-1); 20 q[++t]=S;d[S]=0; 21 while(f<=t){ 22 int x=q[f++]; 23 for(int i=h[x],y;i;i=e[i].nxt) 24 if(d[y=e[i].y]==-1&&e[i].z) 25 d[y]=d[x]+1,q[++t]=y; 26 } return (d[T]!=-1); 27 } int dfs(int x,int f){ 28 if(x==T) return f;int w,tmp=0; 29 for(int i=h[x],y;i;i=e[i].nxt) 30 if(d[y=e[i].y]==d[x]+1&&e[i].z){ 31 w=dfs(y,min(e[i].z,f-tmp)); 32 if(!w) d[y]=-1; 33 e[i].z-=w;e[i^1].z+=w; 34 tmp+=w;if(tmp==f) return f; 35 } return tmp; 36 } void dinic(){ 37 while(bfs()) tot+=dfs(S,inf); 38 } int main(){ 39 scanf("%d",&cas);while(cas--){ 40 scanf("%d%d",&n,&m);flg=0; 41 ms(in,0);ms(ot,0);ms(h,0); 42 c=1;S=0,T=n+1;sm=0,tot=0; 43 for(int i=1;i<=m;i++) 44 scanf("%d%d%d",&w[i].x,&w[i].y,&w[i].d), 45 in[w[i].y]++,ot[w[i].x]++; 46 for(int i=1;i<=n;i++){ 47 if((in[i]&1)^(ot[i]&1)) 48 {flg=1;break;} 49 if(in[i]>ot[i]) //sm+=in[i]-ot[i], 50 add(S,i,(in[i]-ot[i])/2); 51 if(in[i]<ot[i]) sm+=ot[i]-in[i], 52 add(i,T,(ot[i]-in[i])/2); 53 } if(flg){puts("impossible");continue;} 54 for(int i=1;i<=m;i++) 55 if(!w[i].d) add(w[i].y,w[i].x,1); 56 dinic();sm>>=1; 57 if(tot==sm) puts("possible"); 58 else puts("impossible"); 59 } return 0; 60 }