混合图的欧拉回路toj3555

混合图的欧拉回路toj3555

/*混合图的欧拉回路
混合图欧拉回路
原来混合图欧拉回路用的是网络流。
把该图的无向边随便定向,计算每个点的入度和出度。如果有某个点出入度之差为奇数,
那么肯定不存在欧拉回路。因为欧拉回路要求每点入度 = 出度,也就是总度数为偶数,存在奇数度点必不能有欧拉回路。
好了,现在每个点入度和出度之差均为偶数。那么将这个偶数除以2,得x。
也就是说,对于每一个点,只要将x条边改变方向(入>出就是变入,出>入就是变出),
就能保证出 = 入。如果每个点都是出 = 入,那么很明显,该图就存在欧拉回路。
现在的问题就变成了:我该改变哪些边,可以让每个点出 = 入?构造网络流模型。首先,有向边是不能改变方向的,要之无用,删。
一开始不是把无向边定向了吗?定的是什么向,就把网络构建成什么样,边长容量上限1。另新建s和t。对于入 > 出的点u,连接边(u, t)、容量为x,
对于出 > 入的点v,连接边(s, v),容量为x(注意对不同的点x不同)。之后,察看是否有满流的分配。有就是能有欧拉回路,没有就是没有。欧拉回路是哪个?
察看流值分配,将所有流量非0(上限是1,流值不是0就是1)的边反向,就能得到每点入度 = 出度的欧拉图。
由于是满流,所以每个入 > 出的点,都有x条边进来,将这些进来的边反向,OK,入 = 出了。对于出 > 入的点亦然。
那么,没和s、t连接的点怎么办?和s连接的条件是出 > 入,和t连接的条件是入 > 出,那么这个既没和s也没和t连接的点,自然早在开始就已经满足入 = 出了。
那么在网络流过程中,这些点属于“中间点”。我们知道中间点流量不允许有累积的,这样,进去多少就出来多少,反向之后,自然仍保持平衡。
所以,就这样,混合图欧拉回路问题,解了.

上文是pku的discuss中的,下面自己总结一下。
混合图的欧拉回路, 既然是欧拉回路首先图必须是连通的:将所有边看成无向边做一遍dfs判断连通性。
要构成欧拉图最后所以得点入度都等于出度,即需要每个点入度和出度之差为偶数,若有两个点为奇数可能有欧拉路,
这时只需要在这两个点之间加一条边,即可转化为欧拉回路问题。

判断完毕后,如果所有点入度和出度差为偶数,构建网络流图,原来图中的有向边,可以删去。
原来的无向边可以任意指定一个方向,之后对所有入度大于出度的点引一条边到汇点,边权为入度与出度差的一半。
对于出度大于入度的点从源点引一条边过来,边权为出度和入度差的一半,最后求最大流,若是漫流,则证明有欧拉回路。

  1 #include < iostream >
  2 #include < cstdio >
  3 #include < cstring >
  4 using   namespace  std;
  5 #define  MAXV 30
  6 #define  MAXE 100000 
  7 #define  INF 0x1f1f1f1f
  8 int  flag[MAXV],used[MAXV],head[MAXV],q[MAXV],ind[MAXV],outd[MAXV],level[MAXV];
  9 int  src,dest,pe;
 10 int  mp[MAXV][MAXV];
 11 void  dfs( int  x)
 12 {
 13     flag[x]=1;
 14     for(int i=0;i<26;i++)
 15     if(!flag[i]&&mp[x][i])
 16     dfs(i);
 17}

 18 struct  node
 19 {
 20       int v,next,dup;
 21       int cap,f;
 22       node(){}
 23       node(int _v,int _next,int _dup,int _cap,int _f):v(_v),next(_next),dup(_dup),cap(_cap),f(_f){}
 24}
Elist[MAXE];
 25
 26 inline  void  add_edge( int  u, int  v, int  cap, int  f = 0 )
 27 {
 28       Elist[pe]=node(v,head[u],pe+1,cap,f);
 29       head[u]=pe++;
 30       Elist[pe]=node(u,head[v],pe-1,0,-f);
 31       head[v]=pe++;
 32}

 33 bool  dinic_bfs()
 34 {
 35     int qs(0),qe(1),p;
 36     memset(level,-1,sizeof(level));
 37     level[src]=0;
 38     q[0]=src;
 39     while(qs<qe)
 40     {
 41                 for(p=head[q[qs]];p!=-1;p=Elist[p].next)
 42                 {
 43                           if(level[Elist[p].v]==-1&&Elist[p].cap>Elist[p].f)
 44                           {
 45                                 level[Elist[p].v]=level[q[qs]]+1;
 46                                 q[qe++]=Elist[p].v;
 47                           }

 48                 }

 49                 qs++;
 50     }

 51     return level[dest]!=-1;
 52}

 53
 54 int  Dinic() {
 55    int sh, cur, u, i, *stack = q, p;
 56    int ans(0), m;
 57    while(dinic_bfs()){
 58    //    cout<<"after bfs "<<endl;
 59        sh = 1;
 60        stack[0= src;
 61        while(sh != -1){
 62            cur = stack[sh-1];    //一个点的ID接着一个边的ID 
 63            if(cur == dest){
 64                m = (1<<30);
 65                for(i = 1; i < sh; ++i, ++i)
 66                    if(m > Elist[stack[i]].cap - Elist[stack[i]].f){
 67                        m = Elist[stack[i]].cap - Elist[stack[i]].f;
 68                        u = i;
 69                    }

 70                for(i = 1; i < sh; ++i, ++i){
 71                    Elist[stack[i]].f += m;
 72                    Elist[Elist[stack[i]].dup].f -= m;
 73                }

 74                ans += m;
 75                sh = u;
 76            }

 77            else {
 78                for(p = head[cur]; p != -1; p = Elist[p].next)
 79                    if(level[Elist[p].v] == level[cur]+1 &&Elist[p].cap > Elist[p].f){
 80                        stack[sh++= p;
 81                        stack[sh++= Elist[p].v;
 82                        break;
 83                    }

 84                if(p == -1){
 85                    level[cur] = -1;
 86                    --sh, --sh;
 87                }

 88            }

 89        }

 90    }

 91    return ans;
 92}

 93
 94 int  main()
 95 {
 96    int t,test,n,i,f,u,v;
 97    scanf("%d",&test);
 98    for(t=1;t<=test;t++)
 99    {
100           scanf("%d",&n);
101           char str[100];
102           memset(head,-1,sizeof(head));
103           pe=0;
104           memset(mp,0,sizeof(mp));
105           memset(flag,0,sizeof(flag));
106           memset(used,0,sizeof(used));
107           memset(ind,0,sizeof(ind));
108           memset(outd,0,sizeof(outd));
109           src=26;dest=27;
110           for(i=0;i<n;i++)
111           {
112                 scanf("%s",str);
113                 scanf("%d",&f);
114                 u=str[0]-'a';
115                 outd[u]++;
116                 v=str[strlen(str)-1]-'a';
117                 ind[v]++;
118                 mp[u][v]=mp[v][u]=1;
119                 used[u]=used[v]=1;
120                 if(f)
121                 add_edge(u,v,1);
122           }

123           printf("Case %d: ",t);
124           for(i=0;i<26;i++)
125           if(used[i])
126           {
127                dfs(i);
128                break;
129           }

130           for(i=0;i<26;i++)
131           if(used[i]&&!flag[i])
132           {
133              printf("Poor boy!\n");
134              break;
135           }

136           if(i!=26continue;
137           int total,sum;
138           total=sum=0;
139           for(i=0;i<26;i++)
140            if(used[i])
141            {
142                  if((ind[i]-outd[i])%2!=0)
143                  {
144                      total++;
145                      if(total==1)
146                      u=i;
147                      else if(total==2)
148                      v=i;
149                  }

150            }

151            if(total==1||total>2)
152            {
153                    printf("Poor boy!\n");
154                    continue;
155            }

156            if(total==2)
157            {
158                     ind[u]++;
159                     outd[v]++;
160                     add_edge(v,u,1);
161            }

162            for(i=0;i<26;i++)
163            {
164                if(outd[i]>ind[i])
165                {
166                        add_edge(src,i,(outd[i]-ind[i])/2);
167                        sum+=(outd[i]-ind[i])/2;
168                }

169                else if(ind[i]>outd[i])
170                add_edge(i,dest,(ind[i]-outd[i])/2);
171            }

172            int tmp=Dinic();
173            if(tmp==sum)
174            printf("Well done!\n");
175            else
176            printf("Poor boy!\n");
177                  
178           
179    }

180    return 0;
181}
 
182
183

你可能感兴趣的:(混合图的欧拉回路toj3555)