ZOJ 2587 最小割

题意:

给出一个带权无向图,给出图中a,b两个点,已知切断一每条边都会产生与这条边权值相同的消耗,切断某些边可以使得a,b之间不连通,在已知一个切边方法消耗最小的方法,判断是否存在与此切割方法消耗相同的方法。

题解:

判断最小割的唯一性!

就是老样子从S沿着非满流的正向边遍历点的总数k1,从T沿着非满流的正向边遍历的点的总数k2,若k1+k2=n(总点数)时最小割唯一。

哎,成了结论了,不会证明。。

后来又想怎么求最小割的总方案数,也不会。。求大神解释!

 

View Code
 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <cstring>
 6 
 7 #define N 1000
 8 #define M 400000
 9 #define INF 1e9
10 
11 using namespace std;
12 
13 int head[N],to[M],next[M],len[M];
14 int q[M*4],layer[N];
15 bool vis[N];
16 int n,m,S,T,cnt;
17 
18 inline void add(int u,int v,int w)
19 {
20     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
21     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
22 }
23 
24 inline void read()
25 {
26     memset(head,-1,sizeof head); cnt=0;
27     memset(vis,0,sizeof vis);
28     for(int i=1,a,b,c;i<=m;i++)
29     {
30         scanf("%d%d%d",&a,&b,&c);
31         add(a,b,c); add(b,a,c);
32     }
33 }
34 
35 inline bool bfs()
36 {
37     memset(layer,-1,sizeof layer);
38     int h=1,t=2,sta;
39     q[1]=S; layer[S]=0;
40     while(h<t)
41     {
42         sta=q[h++];
43         for(int i=head[sta];~i;i=next[i])
44             if(len[i]&&layer[to[i]]<0)
45             {
46                 layer[to[i]]=layer[sta]+1;
47                 q[t++]=to[i];
48             }
49     }
50     return layer[T]!=-1;
51 }
52 
53 inline int find(int u,int cur_flow)
54 {
55     if(u==T) return cur_flow;
56     int res=0,tmp;
57     for(int i=head[u];~i&&res<cur_flow;i=next[i])
58         if(len[i]&&layer[to[i]]==layer[u]+1)
59         {
60             tmp=find(to[i],min(cur_flow-res,len[i]));
61             len[i]-=tmp; len[i^1]+=tmp; res+=tmp;
62         }
63     if(!res) layer[u]=-1;
64     return res;
65 }
66 
67 inline void dfs1(int u)
68 {
69     vis[u]=1;
70     for(int i=head[u];~i;i=next[i])
71         if(vis[to[i]]==0&&len[i]>0) dfs1(to[i]);
72 }
73 
74 inline void dfs2(int u)
75 {
76     vis[u]=1;
77     for(int i=head[u];~i;i=next[i])
78         if(vis[to[i]]==0&&len[i^1]>0) dfs2(to[i]);
79 }
80 
81 inline void go()
82 {
83     int ans=0;
84     while(bfs()) ans+=find(S,INF);
85     dfs1(S); dfs2(T);
86     for(int i=1;i<=n;i++)
87         if(!vis[i]) {puts("AMBIGUOUS");return;}
88     puts("UNIQUE");
89 }
90 
91 int main()
92 {
93     while(scanf("%d%d%d%d",&n,&m,&S,&T)!=EOF)
94     {
95         if(n==0&&m==0&&S==0&&T==0) break;
96         read(),go();
97     }
98     return 0;
99 } 

 

 

posted @ 2013-01-08 22:27  proverbs  阅读(348)  评论(0编辑  收藏  举报