POJ1637-Sightseeing tour/HDU-3472-HS BDC-最大流Dinic+判断混合图的欧拉图

Posted ofshk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ1637-Sightseeing tour/HDU-3472-HS BDC-最大流Dinic+判断混合图的欧拉图相关的知识,希望对你有一定的参考价值。

前置知识:

混合图:一幅图中既有单向边,又有双向边。

混合图(既有有向边又有无向边的图)中欧拉环、欧拉路径的判定需要用到网络流这个算法!!!

有向图的欧拉回路的条件:所有的节点出度等于入度。

下面这两题基本差不多,但是建边啊、判断欧拉图啊等还是有区别的。

总之最后都是需要判断是否为满流,如果为满流则说明是欧拉回路。

 

注意:

1、tot初始化为-1,因为在进行反向边的时候通过异或是01、23、45、...这样为一组的。

if(di>0)
{
    e[i].flow-=di;
    e[i^1].flow+=di;
    return di;
}

 

2、源点和汇点s和t要搞清楚设置为多少,有些题目设置s=n、t=n+1的时候会造成s->t没有边,从而造成错误。

 

POJ1637-Sightseeing tour

题意:问给出的混合图中是否存在欧拉回路。

每行数据后面的0代表无向,1代表有向。

 

AC代码:

技术图片
  1 #include<string.h>
  2 #include<iostream>
  3 #include<stdio.h>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<vector>
  7 #include<map>
  8 #include<cmath>
  9 using namespace std;
 10 #define inf 0x3f3f3f3f
 11 const int N=220;
 12 typedef long long ll;
 13 
 14 int n,m,s,t,tot;
 15 int head[10*N],dep[10*N],cur[10*N],floww;
 16 int in[N],out[N];
 17 
 18 struct node
 19 {
 20     // int u,v,flow;
 21     int nextt,v,flow;
 22 }e[N*N];
 23 
 24 void add(int u,int v,int flow)
 25 {
 26     tot++;
 27     //nextt[tot]=head[u];
 28     e[tot].nextt=head[u];
 29     head[u]=tot;
 30     // e[tot].u=u;
 31     e[tot].v=v;
 32     e[tot].flow=flow;
 33 
 34     /*  tot++;
 35       // nextt[tot]=head[v];
 36       e[tot].nextt=head[v];
 37       head[v]=tot;
 38       //e[tot].u=v;
 39       e[tot].v=u;
 40       e[tot].flow=0;*/
 41 }
 42 
 43 int dfs(int u,int flow)
 44 {
 45     if(u==t)
 46         return flow;
 47     for(int &i=cur[u]; i!=-1; i=e[i].nextt) //注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的
 48     {
 49         if((dep[e[i].v]==dep[u]+1)&&e[i].flow>0)
 50         {
 51             int di=dfs(e[i].v,min(flow,e[i].flow));
 52             if(di>0)
 53             {
 54                 e[i].flow-=di;
 55                 e[i^1].flow+=di;
 56                 return di;
 57             }
 58         }
 59     }
 60     return -1;
 61 }
 62 
 63 bool bfs()
 64 {
 65     if(s==t)return 0;
 66     queue<int>Q;
 67     while(!Q.empty())
 68         Q.pop();
 69     memset(dep,-1,sizeof(dep));
 70     dep[s]=1;
 71     Q.push(s);
 72     while(!Q.empty())
 73     {
 74         int u=Q.front();
 75         Q.pop();
 76         for (int i=head[u]; i!=-1; i=e[i].nextt)
 77         {
 78             if ((e[i].flow>0)&&(dep[e[i].v]==-1))
 79             {
 80                 dep[e[i].v]=dep[u]+1;
 81                 Q.push(e[i].v);
 82             }
 83         }
 84     }
 85     if(dep[t]!=-1)
 86         return 1;
 87     return 0;
 88 }
 89 
 90 int dinic()
 91 {
 92     int sum=0;
 93     while(bfs())
 94     {
 95         for(int i=s; i<=t; i++)
 96             cur[i]=head[i];
 97         int di;
 98         while((di=dfs(s,inf))!=-1)
 99             sum+=di;
100     }
101     return sum;
102 }
103 
104 bool Euler()
105 {
106     floww=0;
107     for (int i=1; i<=n; i++)
108     {
109         if(in[i]<out[i])
110             floww=floww+((out[i]-in[i])>>1);
111         if((in[i]+out[i])&1)
112             return 0;
113     }
114     return 1;
115 }
116 
117 int main()
118 {
119     int tt;
120     scanf("%d",&tt);
121     while(tt--)
122     {
123         scanf("%d %d",&n,&m);
124         memset(in,0,sizeof(in));
125         memset(out,0,sizeof(out));
126         memset(head,-1,sizeof(head));
127         memset(cur,0,sizeof(cur));
128         s=0,t=n+1,tot=-1;
129         int x,y,z;
130         for(int i=1; i<=m; i++)
131         {
132             scanf("%d %d %d",&x,&y,&z);
133             in[y]++,out[x]++;
134             if(z==0)
135             {
136                 add(x,y,1);
137                 add(y,x,0);
138             }
139         }
140         if(Euler())
141         {
142             for(int i=1; i<=n; i++)
143             {
144                 if(in[i]>out[i])
145                 {
146                     add(i,t,(in[i]-out[i])>>1);
147                     add(t,i,0);
148                 }
149                 else if(out[i]>in[i])
150                 {
151                     add(s,i,(out[i]-in[i])>>1);
152                     add(i,s,0);
153                 }
154             }
155             if(dinic()==floww)
156                 printf("possible
");
157             else
158                 printf("impossible
");
159         }
160         else
161             printf("impossible
");
162     }
163     return 0;
164 }
View Code

这题我的代码再VJ上C++会超时,G++可以过。

以后最好还是用G++交,因为G+兼容C和C++,但有时候C++能过G++不能,都试一下吧如果觉得自己代码实在是没问题了。

输出double时,用G++提交时,scanf用%lf,prinf用%f,否则报错。

 

HDU-3472-HS BDC

题意:

给n个字符串,如果某个字符串的最后一个字母和另外一个字符串的第一个字母字母一样,那么这两个字母就可以连起来,有的字符串可以反转,问是否存在一种情况使得所有字符串都连成链。

 

思路:

要知道判断的是欧拉回路或者欧拉通路,二者取其一即可;

字符串的第一个字母–>字符串的最后一个字母建一条有向边,再判断字符串后面的数字x,看是否能够建立一条反向边,如果可以建立,则说明这条边是一条无向边,从而构成了一幅混合图

由于成链而不是成环,所以可以利用Dinic中的SPFA,因为SPFA无法处理环。

 

但是这一题首先要判断一下建的图的连通性,只有满足连通才能进行下一步的判断

 

AC代码:

技术图片
  1 #include<string.h>
  2 #include<iostream>
  3 #include<stdio.h>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<vector>
  7 #include<map>
  8 #include<cmath>
  9 using namespace std;
 10 #define inf 0x3f3f3f3f
 11 const int N=220;
 12 typedef long long ll;
 13 
 14 int n,m,tot,s,t;
 15 int head[10*N],dep[10*N],cur[10*N],floww;
 16 int in[30],out[30],f[30];
 17 char str[30];
 18 
 19 struct node
 20 {
 21     // int u,v,flow;
 22     int nextt,v,flow;
 23 } e[N*N];
 24 
 25 void add(int u,int v,int flow)
 26 {
 27     tot++;
 28     //nextt[tot]=head[u];
 29     e[tot].nextt=head[u];
 30     head[u]=tot;
 31     // e[tot].u=u;
 32     e[tot].v=v;
 33     e[tot].flow=flow;
 34 
 35       tot++;
 36       // nextt[tot]=head[v];
 37       e[tot].nextt=head[v];
 38       head[v]=tot;
 39       //e[tot].u=v;
 40       e[tot].v=u;
 41       e[tot].flow=0;
 42 }
 43 
 44 int dfs(int u,int flow)
 45 {
 46     if(u==t)
 47         return flow;
 48     for(int &i=cur[u]; i!=-1; i=e[i].nextt) //注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的
 49     {
 50         if((dep[e[i].v]==dep[u]+1)&&e[i].flow>0)
 51         {
 52             int di=dfs(e[i].v,min(flow,e[i].flow));
 53             if(di>0)
 54             {
 55                 e[i].flow-=di;
 56                 e[i^1].flow+=di;
 57                 return di;
 58             }
 59         }
 60     }
 61     return -1;
 62 }
 63 
 64 bool bfs()
 65 {
 66     if(s==t)
 67         return 0;
 68     queue<int>Q;
 69     while(!Q.empty())
 70         Q.pop();
 71     memset(dep,-1,sizeof(dep));
 72     dep[s]=1;
 73     Q.push(s);
 74     while(!Q.empty())
 75     {
 76         int u=Q.front();
 77         Q.pop();
 78         for (int i=head[u]; i!=-1; i=e[i].nextt)
 79         {
 80             if ((e[i].flow>0)&&(dep[e[i].v]==-1))
 81             {
 82                 dep[e[i].v]=dep[u]+1;
 83                 Q.push(e[i].v);
 84             }
 85         }
 86     }
 87     if(dep[t]!=-1)
 88         return 1;
 89     return 0;
 90 }
 91 
 92 int dinic()
 93 {
 94     int sum=0;
 95     while(bfs())
 96     {
 97         for(int i=s; i<=t; i++)
 98             cur[i]=head[i];
 99         int di;
100         while((di=dfs(s,inf))!=-1)
101             sum+=di;
102     }
103     return sum;
104 }
105 
106 //bool Euler()
107 //{
108 //    floww=0;
109 //    for (int i=1; i<=26; i++)
110 //    {
111 //        if(in[i]<out[i])
112 //            floww=floww+((out[i]-in[i])>>1);
113 //        if((in[i]+out[i])&1)
114 //            return 0;
115 //    }
116 //    return 1;
117 //}
118 
119 int getf(int x)
120 {
121     if(f[x]==x)
122         return x;
123     return f[x]=getf(f[x]);
124 }
125 
126 void merge(int x,int y)
127 {
128     int t1=getf(x);
129     int t2=getf(y);
130     f[t2]=t1;
131 }
132 
133 bool judge_unpass()
134 {
135     int x=0;
136     for(int i=1; i<=26; i++)
137     {
138         if(abs(in[i]-out[i])&1)
139             x++;
140     }
141     if(x!=0&&x!=2)
142         return 1;
143     x=0;
144     for(int i=1; i<=26; i++)
145     {
146         if((in[i]+out[i])&&f[i]==i)
147             x++;
148     }
149     if(x>=2)
150         return 1;
151     return 0;
152 }
153 
154 int main()
155 {
156     int cas=1,T;
157     scanf("%d",&T);
158     while(T--)
159     {
160         memset(in,0,sizeof(in));
161         memset(out,0,sizeof(out));
162         memset(head,-1,sizeof(head));
163         memset(cur,0,sizeof(cur));
164         s=0,t=27,tot=-1;
165         for(int i=1; i<=26; i++)
166             f[i]=i;
167         scanf("%d",&m);
168         for(int i=1; i<=m; i++)
169         {
170             int x;
171             scanf("%s %d",str,&x);
172             int len=strlen(str);
173             int ss=str[0]-a+1;
174             int tt=str[len-1]-a+1;
175             in[tt]++,out[ss]++;
176             merge(ss,tt);
177             if(x)
178             {
179                 add(ss,tt,1);
180                 //add(tt,ss,0);WA??
181             }
182         }
183         if(judge_unpass())
184             printf("Case %d: Poor boy!
",cas++);
185         else
186         {
187             int sum=0;
188             for(int i=1; i<=26; i++)
189             {
190                 if(in[i]==0&&out[i]==0)
191                     continue;
192                 if(out[i]>in[i])
193                 {
194                     add(s,i,abs(in[i]-out[i])>>1);
195                     sum+=abs(in[i]-out[i])>>1;
196                 }
197                 else if(out[i]<in[i])
198                     add(i,t,abs(in[i]-out[i])>>1);
199             }
200             if(dinic()==sum)
201                 printf("Case %d: Well done!
",cas++);
202             else
203                 printf("Case %d: Poor boy!
",cas++);
204         }
205     }
206     return 0;
207 }
View Code

 

以上是关于POJ1637-Sightseeing tour/HDU-3472-HS BDC-最大流Dinic+判断混合图的欧拉图的主要内容,如果未能解决你的问题,请参考以下文章

网络流(最大流) POJ 1637 Sightseeing tour

POJ 1637 Sightseeing tour (混合图欧拉回路)

POJ1637:Sightseeing tour(混合图的欧拉回路)

POJ1637 Sightseeing tour (混合图欧拉回路)(网络流)

poj 1637 Sightseeing tour —— 最大流+欧拉回路

poj1637Sightseeing tour