zoj 2587 判断最小割的唯一性

算法:

  先求出残量网络,计算出从src能够到的点集A,再求出能够到dst的点集B,如果所有点都被访问到了,那么割就是唯一的,即(A,B),否则(A,V-A)和(V-B,B)都是最小割。

  (注意因为割的本质是有向边集,而不是点集V的划分,所以(A,V-A)和(V-B,B)有可能本质上还是同一个最小割,比如随便再加一个孤立点,虽然割还是唯一的,但还是有点没有被访问到,所以我们限制原图中所有点要么可以从src到达,要么可以到达dst)

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <vector>
  4 #define N 810
  5 #define oo 0x3f3f3f3f
  6 using namespace std;
  7
  8 struct Edge {
  9     int u, v, f;
 10     Edge( int u, int v, int f ):u(u),v(v),f(f){}
 11 };
 12 int n, m, src, dst;
 13 vector<Edge> edge;
 14 vector<int> g[N];
 15 int dep[N], cur[N], qu[N], bg, ed;
 16 bool vis[N];
 17
 18 void init( int n ) {
 19     edge.clear();
 20     for( int u=1; u<=n; u++ )
 21         g[u].clear();
 22 }
 23 void adde( int u, int v, int f ) {
 24     g[u].push_back( edge.size() );
 25     edge.push_back( Edge(u,v,f) );
 26     g[v].push_back( edge.size() );
 27     edge.push_back( Edge(v,u,0) );
 28 }
 29 bool bfs() {
 30     memset( dep, 0, sizeof(dep) );
 31     qu[bg=ed=1] = src;
 32     dep[src] = 1;
 33     while( bg<=ed ) {
 34         int u=qu[bg++];
 35         for( int t=0; t<g[u].size(); t++ ) {
 36             Edge &e = edge[g[u][t]];
 37             if( e.f && !dep[e.v] ) {
 38                 dep[e.v] = dep[e.u]+1;
 39                 qu[++ed] = e.v;
 40             }
 41         }
 42     }
 43     return dep[dst];
 44 }
 45 int dfs( int u, int a ) {
 46     if( u==dst || a==0 ) return a;
 47     int remain=a, past=0, na;
 48     for( int &t=cur[u]; t<g[u].size(); t++ ) {
 49         Edge &e=edge[g[u][t]];
 50         Edge &ve=edge[g[u][t]^1];
 51         if( e.f && dep[e.v]==dep[e.u]+1 && (na=dfs(e.v,min(remain,e.f))) ) {
 52             remain -= na;
 53             past += na;
 54             e.f -= na;
 55             ve.f += na;
 56             if( !remain ) break;
 57         }
 58     }
 59     return past;
 60 }
 61 int maxflow() {
 62     int flow = 0;
 63     while( bfs() ) {
 64         memset( cur, 0, sizeof(cur) );
 65         flow += dfs(src,oo);
 66     }
 67     return flow;
 68 }
 69 bool check() {
 70     int cnt = 0;
 71     memset( vis, 0, sizeof(vis) );
 72     qu[bg=ed=1] = src;
 73     vis[src] = true;
 74     cnt++;
 75     while( bg<=ed ) {
 76         int u=qu[bg++];
 77         for( int t=0; t<g[u].size(); t++ ) {
 78             Edge &e = edge[g[u][t]];
 79             if( e.f && !vis[e.v] ) {
 80                 qu[++ed] = e.v;
 81                 vis[e.v] = true;
 82                 cnt++;
 83             }
 84         }
 85     }
 86     qu[bg=ed=1] = dst;
 87     vis[dst] = true;
 88     cnt++;
 89     while( bg<=ed ) {
 90         int u=qu[bg++];
 91         for( int t=0; t<g[u].size(); t++ ) {
 92             Edge &e = edge[g[u][t]^1];
 93             if( e.f && !vis[e.u] ) {
 94                 qu[++ed] = e.u;
 95                 vis[e.u] = true;
 96                 cnt++;
 97             }
 98         }
 99     }
100     return n==cnt;
101 }
102 int main() {
103     while(1) {
104         scanf( "%d%d%d%d", &n, &m, &src, &dst );
105         if( n==0 && m==0 && src==0 && dst==0 ) return 0;
106         init(n);
107         for( int i=1,u,v,f; i<=m; i++ ) {
108             scanf( "%d%d%d", &u, &v, &f );
109             adde( u, v, f );
110             adde( v, u, f );
111         }
112         maxflow();
113         printf( "%s\n", check() ? "UNIQUE" : "AMBIGUOUS" );
114     }
115 }

时间: 2024-10-29 19:10:28

zoj 2587 判断最小割的唯一性的相关文章

ZOJ 2587 Unique Attack (判断最小割的唯一性)

ZOJ 2587 Unique Attack 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1587 题意:N 台超级计算机连成一个网络.M 对计算机之间用光纤直接连在一起,光纤的连接是双向的.数据可以直接在有光纤直接连接的计算机之间传输,也可以通过一些计算机作为中转来传输. 有一群恐怖分子计划攻击网络.他们的目标是将网络中两台主计算机断开,这样这两台计算机之间就无法传输数据了.恐怖分子已经计算好了摧毁每条光纤所需要花

ZOJ 2587 Unique Attack 判断最小割是否唯一

很裸的判断最小割是否唯一.判断方法是先做一遍最大流求最小割,然后从源点和汇点分别遍历所有能够到达的点,看是否覆盖了所有的点,如果覆盖了所有的点,那就是唯一的,否则就是不唯一的. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostr

zoj 2587 Unique Attack 【判断最小割是否唯一】

Unique Attack Time Limit: 5 Seconds      Memory Limit: 32768 KB N supercomputers in the United States of Antarctica are connected into a network. A network has a simple topology: M different pairs of supercomputers are connected to each other by an o

zoj2587 Unique Attack 判断最小割是否唯一

题目链接: zoj2587 题意: 给出一张无向网络图,并给出起点和终点,破坏图的每一条边需要一定的费用,问破坏起点和终点的连通性的费用是否唯一. 解题思路: 破坏两点的连通性的最小费用,很容易联想到 网络流中的最小割, 建立源点 汇点 同时 因为图是无向图,我们需要将每条边建两次(正反向). 然后就是判断这个最小割是否唯一了: 首先 从源点开始 dfs  通过非饱和边  统计所有能走到的点  记为s1 然后 从汇点开始 dfs  通过非饱和边  统计所有能走到的点 记为s2 如果s1+s2==

最小割5题

S-T割将集合分为两个部分 1.Dual Core CPU http://poj.org/problem?id=3469 题目分析: 双核cpu,有n个的模块,给出第i个模块在第一个核运行的费用和在第二个核运行的费用.以及m对模块如果不在同一个核中运行要多耗费的费用.求最小费用 分析: 注:ai为第i个模块在第一个核运行的耗费,bi为第i个模块在第二个核运行的耗费 cpu的两个核分别当做源点和汇点,源点与模块i连一条边,容量为ai,i与汇点连一条边,容量为bi.对于有限制的模块,连边(u,v)(

ZOJ 2587 Unique Attack(最小割唯一性判断)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2587 题意:判断最小割是否唯一. 思路: 最小割唯一性的判断是先跑一遍最大流,然后在残留网络中分别从源点和汇点出发dfs,只有当该边还有流量可用时可以访问下一个顶点,最后如果所有顶点都访问了,那么就是唯一的,否则不唯一. 接下来图解一下: 先看下面这个容量均为1的图: 跑一遍最大流后的残留网络如下(只画正向弧): 接下来从源点和汇点出发都无法访问任何顶点,因为剩余流量皆为

zoj 2587 Unique Attack 最小割判定

题目链接 让你判断最小割是否唯一. 判断方法是, 先求一遍最大流, 然后从源点dfs一次, 搜索未饱和边的数目. 从汇点dfs一次, 同样也是搜索未饱和边的数目, 看总和是否等于n. 如果等于n那么唯一. 具体可以看这里, http://www.cnblogs.com/Lyush/archive/2013/05/01/3053640.html. 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mem(a) memset(a,

zoj 2676 Network Wars(最小割,01分数规划)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2676 大致题意:给出一个带权无向图,每条边有一个边权wi,求将S和T分开的一个割边集C,使得该割边集的平均边权最小,即最小化∑wi / |C| . 详见amber关于最小割模型的论文 思路:amber论文中详细讲解了如何转化成函数及建图,值得注意的是当边被重新赋权后,对于wi < 0 的边权,该边必然在最小割中,不必再建边,直接加入最大流中即可,因为求最小割时边权都为正值

ZOJ 3792 Romantic Value(网络流之最小割)(找割边)

题目地址:ZOJ 3792 最小割做的太少..这题很明显是找割边.找割边就是判断正向弧是否是0.如果跑完一次最小割后正向弧流量为0的话,那就说明这个边为一条割边.但是找到了割边后再怎么办呢..中午睡觉的时候突然来了灵感..再利用这些割边求一次最大流不就行了..把割边的流量都设为1,其他的都为正无穷.那最后的流量就是最少需要的割边了.然后计算就可以了. 这次又把上限值直接设为sink+1了...导致WA了12发.....sad...以后得注意... 代码如下: #include <iostream