poj 1637 Sightseeing tour

给定一张m个点s条边混合图(有向边和无向边),求是否存在欧拉回路。

1<=m<=200.1<=s<=1000.

混合图欧拉回路需要借助最大流。

有向图欧拉回路的充要条件:图联通且每个点入度等于出度。所以转化为有向图,将每条无向边任意定向,统计入出度。考虑将一条有向边反向会让点的入出度差的绝对值变化2,即若存在某点入出度之差为奇数,则不存在欧拉回路。

如果入出度之差为偶数,则建图网络流判断。

对于每条无向边,按刚才定的向连一条容量为1的边。

源点向所有出度大于入度的点连一条容量为入出度差绝对值除以2的边。

所有入度大于出度的点向汇点连一条容量为入出度差绝对值除以2的边。

跑最大流,若满流则存在欧拉回路,否则不存在。

若存在,将所有流量不为0的边反向,所有点的入出度差均变为0,即可得到一张存在欧拉回路的有向图。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<queue>
  6 using namespace std;
  7 const int dian=205;
  8 const int bian=3005;
  9 const int INF=0x3f3f3f3f;
 10 int h[dian],ver[bian],val[bian],nxt[bian],ch[dian],cr[dian];
 11 int ru[dian],chu[dian];
 12 int cas,n,m,tot,aa,bb,ok;
 13 int S,T;
 14 int aabs(int a){
 15     if(a<0)
 16         return -a;
 17     return a;
 18 }
 19 void add(int a,int b,int c){
 20     tot++;ver[tot]=b;val[tot]=c;nxt[tot]=h[a];h[a]=tot;
 21     tot++;ver[tot]=a;val[tot]=0;nxt[tot]=h[b];h[b]=tot;
 22 }
 23 bool tell(){
 24     memset(ch,-1,sizeof(ch));
 25     queue<int>q;
 26     q.push(S);
 27     ch[S]=0;
 28     while(!q.empty()){
 29         int t=q.front();
 30         q.pop();
 31         for(int i=h[t];i;i=nxt[i])
 32             if(ch[ver[i]]==-1&&val[i]){
 33                 ch[ver[i]]=ch[t]+1;
 34                 q.push(ver[i]);
 35             }
 36     }
 37     return ch[T]!=-1;
 38 }
 39 int zeng(int a,int b){
 40     if(a==T)
 41         return b;
 42     int r=0;
 43     for(int i=cr[a];i&&b>r;i=nxt[i])
 44         if(ch[ver[i]]==ch[a]+1&&val[i]){
 45             int t=zeng(ver[i],min(b-r,val[i]));
 46             val[i]-=t,r+=t,val[i^1]+=t;
 47             if(val[i])
 48                 cr[a]=i;
 49         }
 50     if(!r)
 51         ch[a]=-1;
 52     return r;
 53 }
 54 int dinic(){
 55     int r=0,t;
 56     while(tell()){
 57         for(int i=1;i<=n+2;i++)
 58             cr[i]=h[i];
 59         while(t=zeng(S,INF))
 60             r+=t;
 61     }
 62     return r;
 63 }
 64 int main(){
 65     scanf("%d",&cas);
 66     while(cas--){
 67         memset(h,0,sizeof(h));
 68         memset(nxt,0,sizeof(nxt));
 69         memset(ru,0,sizeof(ru));
 70         memset(chu,0,sizeof(chu));
 71         tot=1;
 72         scanf("%d%d",&n,&m);
 73         S=n+1,T=n+2;
 74         for(int i=1;i<=m;i++){
 75             scanf("%d%d%d",&aa,&bb,&ok);
 76             chu[aa]++;
 77             ru[bb]++;
 78             if(!ok)
 79                 add(aa,bb,1);
 80         }
 81         int lala=0;
 82         for(int i=1;i<=n;i++)
 83             if(aabs(ru[i]-chu[i])&1){
 84                 lala=1;
 85                 break;
 86             }
 87         if(lala){
 88             printf("impossible\n");
 89             continue;
 90         }
 91         int ans=0;
 92         for(int i=1;i<=n;i++){
 93             if(ru[i]==chu[i])
 94                 continue;
 95             if(ru[i]>chu[i])
 96                 add(i,T,(ru[i]-chu[i])/2);
 97             else{
 98                 add(S,i,(chu[i]-ru[i])/2);
 99                 ans+=(chu[i]-ru[i])/2;
100             }
101         }
102         if(dinic()==ans)
103             printf("possible\n");
104         else
105             printf("impossible\n");
106     }
107     return 0;
108 }

PS:代码忘了判图连通,不知道题目有没有保证,poj数据过了,懒得加了就这样吧。

 

posted @ 2017-01-03 09:44  dugudashen  阅读(163)  评论(0编辑  收藏  举报