[Poj]1637——混合图欧拉回路

[题目大意]
  • 给定一张混合图,求是否可能存在欧拉回路(拓展:输出方案)

[分析题解]
  •     把该图的无向边随便定向,计算每个点的入度和出度。如果有某个点出入度之差为奇数,那么肯定不存在欧拉回路。 因为欧拉回路要求每点入度 = 出度,也就是总度数为偶数,存在奇数度点必不能有欧拉回路。

        好了,现在每个点入度和出度之差均为偶数。那么将这个偶数除以2,得x。也就是说,对于每一个点,只要将x条边改变方向(入>出就是变入,出>入就是变出),就能保证出 = 入。如果每个点都是出 = 入,那么很明显,该图就存在欧拉回路。

        现在的问题就变成了:我该改变哪些边,可以让每个点出 = 入?构造网络流模型。

        首先,有向边是不能改变方向的,要之无用,删。一开始不是把无向边定向了吗?定的是什么向,就把网络构建成什么样,边长容量上限1。另新建s和t。对于入 > 出的点u,连接边(u, t)、容量为x,对于出 > 入的点v,连接边(s, v),容量为x(注意对不同的点x不同)。
        之后,察看从S发出的所有边是否满流。有就是能有欧拉回路,没有就是没有。欧拉回路是哪个?察看流值分配,将所有流量非 0(上限是1,流值不是0就是1)的边反向,就能得到每点入度 = 出度的欧拉图。 
        由于是满流,所以每个入 > 出的点,都有x条边进来,将这些进来的边反向,OK,入 = 出了。对于出 > 入的点亦然。那么,没和s、t连接的点怎么办?和s连接的条件是出 > 入,和t连接的条件是入 > 出,那么这个既没和s也没和t连接的点,自然早在开始就已经满足入 = 出了。那么在网络流过程中,这些点属于“中间点”。我们知道中间点流量不允许有累积的,这样,进去多少就出来多少,反向之后,自然仍保持平衡。 
        所以,就这样,混合图欧拉回路问题,解了。


[个人代码]
View Code
  1 Const
  2   Inf=10000000;
  3   MaxEdge=(100000+100)*2;
  4   MaxNode=10000+100;
  5 
  6 Var
  7   n,m,ans,tot,Src,Sink,CaseNum:Longint;
  8   Edge:Array [0..MaxEdge] of Record c,wh,bak,next:Longint;end;
  9   Hv,St,Next,Line,Pin,Pout,Lv,Bak:Array [0..MaxNode] of Longint;
 10   u,v,d:Array [0..MaxEdge] of Longint;
 11   {$IFDEF LD}Flow:Longint;{$ENDIF}
 12 
 13 Procedure Init;
 14   var
 15     i:Longint;
 16   begin
 17     readln(n,m);
 18     Fillchar(Pin,Sizeof(Pin),0);
 19     Fillchar(Pout,Sizeof(Pout),0);
 20     for i:=1 to m do
 21       begin
 22         readln(u[i],v[i],d[i]);
 23         Inc(Pout[u[i]]);
 24         Inc(Pin[v[i]]);
 25       end;
 26   end;
 27 
 28 Function SpCheck:Boolean;
 29   var
 30     i:Longint;
 31   begin
 32     For i:=1 to n do
 33       If abs(Pin[i]-Pout[i]) and 1=1 then
 34         begin
 35           writeln('impossible');
 36           Exit(True);
 37         end;
 38     Exit(False);
 39   end;
 40 
 41 Procedure AddEdge(u,v,c:Longint);
 42   begin
 43     inc(tot);
 44     Edge[tot].next:=hv[u];hv[u]:=tot;
 45     Edge[tot].wh:=v;Edge[tot].c:=c;
 46     inc(tot);
 47     Edge[tot].next:=hv[v];hv[v]:=tot;
 48     Edge[tot].wh:=u;Edge[tot].c:=0;
 49     Edge[tot].bak:=tot-1;Edge[tot-1].bak:=tot;
 50   end;
 51 
 52 Procedure BuildMap;
 53   var
 54     i:Longint;
 55   begin
 56     tot:=0;
 57     Fillchar(Hv,Sizeof(Hv),0);
 58     Src:=n+1;Sink:=n+2;
 59     For i:=1 to m do
 60       if d[i]=0 then
 61         AddEdge(u[i],v[i],1);
 62     For i:=1 to n do
 63       begin
 64         if Pin[i]=Pout[i] then Continue;
 65         if Pin[i]-Pout[i]>0 then AddEdge(i,Sink,(Pin[i]-Pout[i]) shr 1else AddEdge(Src,i,(Pout[i]-Pin[i]) shr 1);
 66       end;
 67   end;
 68 
 69 Function Dinic_BFS:Boolean;
 70   var
 71     top,tail,u,v,tnode:Longint;
 72   begin
 73     Fillchar(Lv,Sizeof(Lv),0);Lv[Src]:=1;
 74     top:=0;tail:=1;Line[1]:=Src;
 75     Repeat
 76       inc(top);
 77       u:=Line[top];
 78       tnode:=hv[u];
 79       while tnode<>0 do
 80         begin
 81           v:=Edge[tnode].wh;
 82           if (Edge[tnode].c>0)and(Lv[v]=0then
 83             begin
 84               Lv[v]:=Lv[u]+1;
 85               if v=Sink then Exit(False);
 86               Inc(tail);
 87               Line[tail]:=v;
 88             end;
 89           tnode:=Edge[tnode].next;
 90         end;
 91     Until top=tail;
 92     if Lv[Sink]=0 then Exit(True) else Exit(False);
 93   end;
 94 
 95 Function Dinic_DFS:Longint;
 96   var
 97     Res,top,u,v,tnode,Min,I:Longint;
 98   begin
 99     Res:=0;
100     top:=1;St[1]:=Src;
101     Repeat
102       u:=St[top];
103       tnode:=hv[u];
104       while tnode<>0 do
105         begin
106           v:=Edge[tnode].wh;
107           if (Edge[tnode].c>0)and(lv[v]=lv[u]+1then
108             begin
109               Bak[top]:=tnode;
110               inc(top);
111               St[top]:=v;
112               Break;
113             end;
114           tnode:=Edge[tnode].next;
115         end;
116       if St[top]=sink then
117         begin
118           Min:=MaxLongint;
119           For I:=1 to top-1 do
120             if Edge[Bak[I]].c<Min then Min:=Edge[Bak[I]].c;
121           Inc(Res,Min);
122           For I:=1 to top-1 do
123             begin
124               Dec(Edge[Bak[I]].c,Min);Inc(Edge[Edge[Bak[I]].Bak].c,Min);
125             end;
126           For I:=1 to top-1 do
127             if Edge[Bak[I]].c=0 then
128               begin
129                 top:=I;
130                 Break;
131               end;
132         end
133       else if tnode=0 then begin lv[St[top]]:=Inf;dec(top);end;
134     Until top=0;
135     Exit(Res);
136   end;
137 
138 Procedure Dinic;
139   begin
140     While Not(Dinic_BFS) do
141       Dinic_DFS;
142   end;
143 
144 Function SpCheckForEdge:Boolean;
145   var
146     tnode:Longint;
147   begin
148     tnode:=Hv[Src];
149     While tnode<>0 do
150       begin
151         if Edge[tnode].c>0 then Exit(False);
152         tnode:=Edge[tnode].next;
153       end;
154     Exit(True);
155   end;
156 
157 Procedure Main;
158   begin
159     ans:=0;
160     BuildMap;
161     {$IFDEF LD}Flow:=0;{$ENDIF}
162     Dinic;
163     {$IFDEF LD}writeln('               $LD   ','Flow=',Flow);{$ENDIF}
164     if SpCheckForEdge then ans:=1;
165   end;
166 
167 Procedure Print;
168   begin
169     if ans=0 then writeln('impossible'else writeln('possible');
170   end;
171 
172 Begin
173   {$IFDEF LD}Assign(INPUT,'P1637.in');Reset(INPUT);{$ENDIF}
174   Readln(CaseNum);
175   while not(CaseNum=0do
176     begin
177       Dec(CaseNum);
178       Init;
179       If Not(SpCheck) then
180         begin
181           Main;
182           Print;
183         end;
184     end;
185   {$IFDEF LD}Close(INPUT);{$ENDIF}
186 End.

[相关链接] 
  1.  

[启发总结]
  1.  连WA带TLE了十多次,最后发现是Dinic写错了-_-!桑心呀!!!
posted @ 2012-05-17 20:04  PerSeAwe  阅读(258)  评论(0编辑  收藏  举报