[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连接的点,自然早在开始就已经满足入 = 出了。那么在网络流过程中,这些点属于“中间点”。我们知道中间点流量不允许有累积的,这样,进去多少就出来多少,反向之后,自然仍保持平衡。
所以,就这样,混合图欧拉回路问题,解了。
[个人代码]
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 1) else 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]=0) then
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]+1) then
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=0) do
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.
[相关链接]
[启发总结]
- 连WA带TLE了十多次,最后发现是Dinic写错了-_-!桑心呀!!!
——————————————————————————————————————
你说,我们的存在,永不消逝。对吧?
如果,我们都在努力创造了存在。我们,会幸福的。对吧?