生活随笔
收集整理的這篇文章主要介紹了
poj 1637(混合图求欧拉回路)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
參考博客:http://www.cnblogs.com/destinydesigner/archive/2009/09/28/1575674.html
1 定義
歐拉通路 (Euler tour)——通過圖中每條邊一次且僅一次,并且過每一頂點的通路。
歐拉回路 (Euler circuit)——通過圖中每條邊一次且僅一次,并且過每一頂點的回路。
歐拉圖——存在歐拉回路的圖。
2 無向圖是否具有歐拉通路或回路的判定
G有歐拉通路的充分必要條件為:G 連通,G中只有兩個奇度頂點(它們分別是歐拉通路的兩個端點)。
G有歐拉回路(G為歐拉圖):G連通,G中均為偶度頂點。
3 有向圖是否具有歐拉通路或回路的判定
D有歐拉通路:D連通,除兩個頂點外,其余頂點的入度均等于出度,這兩個特殊的頂點中,一個頂點的入度比出度大1,另一個頂點的入度比出度小1。
D有歐拉回路(D為歐拉圖):D連通,D中所有頂點的入度等于出度。
4 混合圖。混合圖也就是無向圖與有向圖的混合,即圖中的邊既有有向邊也有無向邊。
5 混合圖歐拉回路
混合圖歐拉回路用的是網絡流。
把該圖的無向邊隨便定向,計算每個點的入度和出度。如果有某個點出入度之差為奇數,那么肯定不存在歐拉回路。因為歐拉回路要求每點入度 = 出度,也就是總度數為偶數,存在奇數度點必不能有歐拉回路。
現在每個點入度和出度之差均為偶數。將這個偶數除以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連接的點,自然早在開始就已經滿足入 = 出了。那么在網絡流過程中,這些點屬于“中間點”。我們知道中間點流量不允許有累積的,這樣,進去多少就出來多少,反向之后,自然仍保持平衡。
所以,就這樣,混合圖歐拉回路問題,解了。
View Code 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<cmath>
6 #include<queue>
7 using namespace std;
8 #define N 202
9 #define M 5005
10 #define inf 0x3f3f3f3f
11 queue<
int>
q;
12 struct edge{
13 int to,next,c,f;
14 }e[M];
15 int pre[N],level[N],
in[N];
16 int T,S,cnt;
17 void addedge(
int u,
int v,
int c){
18 e[cnt].f=
0,e[cnt].to=v,e[cnt].c=c,e[cnt].next=pre[u],pre[u]=cnt++
;
19 e[cnt].f=
0,e[cnt].to=u,e[cnt].c=
0,e[cnt].next=pre[v],pre[v]=cnt++
;
20 }
21 bool dinic_bfs(){
22 memset(level,
0,
sizeof(level));
23 q.push(S);
24 level[S]=
1;
25 while(!
q.empty()){
26 int u=
q.front();q.pop();
27 for(
int edg=pre[u];edg!=
0;edg=
e[edg].next){
28 int v=
e[edg].to;
29 if(!level[v]&&e[edg].c>
e[edg].f){
30 level[v]=level[u]+
1;
31 q.push(v);
32 }
33 }
34 }
35 return level[T]!=
0;
36 }
37 int dinic_dfs(
int u,
int cp){
38 int tmp=
cp;
39 if(T==u)
return cp;
40 for(
int edg=pre[u];edg!=
0&&tmp;edg=
e[edg].next){
41 int v=
e[edg].to;
42 if(level[v]==level[u]+
1&&e[edg].c>
e[edg].f){
43 int t=dinic_dfs(v,min(tmp,e[edg].c-
e[edg].f));
44 e[edg].f+=
t;
45 e[edg^
1].f-=
t;
46 tmp-=
t;
47 }
48 }
49 return cp-
tmp;
50 }
51 bool dinic(
int s){
52 int tf=
0,f=
0;
53 while(dinic_bfs()){
54 while(f=
dinic_dfs(S,inf)){
55 tf+=
f;
56 }
57 }
58
59 return tf==
s;
60 }
61 int main(){
62 int ca;
63 scanf(
"%d",&
ca);
64 while(ca--
){
65 int m,s,flag=
1;
66 memset(pre,
0,
sizeof(pre));
67 memset(
in,
0,
sizeof(
in));
68 scanf(
"%d%d",&m,&s);S=
0;
69 T=m+
1;cnt=
2;
70 while(s--
){
71 int u,v,c;
72 scanf(
"%d%d%d",&u,&v,&
c);
73 in[u]--;
in[v]++
;
74 if(!c)addedge(u,v,
1);
75 }
76 for(
int i=
1;i<=m;i++
)
77 {
78 if(
in[i]&
1)flag=
0;
79 }
80 int sum=
0;
81 if(flag){
82 for(
int i=
1;i<=m;i++
){
83 if(
in[i]>
0){addedge(i,T,
in[i]>>
1);sum+=
in[i]>>
1;}
84 if(
in[i]<
0)addedge(S,i,(-
in[i])>>
1);
85 }
86 }
87 if(!dinic(sum))flag=
0;
88 if(!flag)printf(
"impossible\n");
89 else printf(
"possible\n");
90 }
91 return 0;
92 }
?
轉載于:https://www.cnblogs.com/huangriq/archive/2012/08/12/2634233.html
總結
以上是生活随笔為你收集整理的poj 1637(混合图求欧拉回路)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。