1. 程式人生 > >POJ 1637 Sightseeing tour 建圖+網絡流

POJ 1637 Sightseeing tour 建圖+網絡流

必須 style con spl mem 混合 namespace 分享圖片 poj

題意:

  給定一個混合圖,所謂混合圖就是圖中既有單向邊也有雙向邊,現在求這樣的圖是否存在歐拉回路。

分析:

  存在歐拉回路的有向圖,必須滿足[入度==出度],現在,有些邊已經被定向,所以我們直接記錄度數即可,對於無向邊呢?

  對於這樣的邊,我們只需要先隨便定向,然後記錄出入度。(這些邊只用來計算出入度,不用於網絡流建圖)

  然後我們開始建圖。現在極有可能有些點是不滿足[入度==出度]的,所以我們要通過一些變向操作,使得圖中所有點滿足判定。

  如果一個點入度和出度的奇偶性不同,那整張圖一定是不合法的。因為改變一條邊的方向對端點的入度和出度是同時影響的,且是反向的,比如入度加一出度減一,或者出度加一入度減一,因此無論如何,那樣的點都不可能滿足判定條件的;

  隨後,我們對於:

  所有入度>出度的點,從超級源點連一條容量為(入度-出度)/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 }
最大流

  

POJ 1637 Sightseeing tour 建圖+網絡流