您的位置:首页 > 其它

poj 1637 Sightseeing tour

2017-01-03 09:44 381 查看

给定一张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数据过了,懒得加了就这样吧。

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: