博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ZOJ-2587 Unique Attack 最小割的唯一性判定
阅读量:6798 次
发布时间:2019-06-26

本文共 2896 字,大约阅读时间需要 9 分钟。

题意:给定一个无向图,要求判定分离两个点的最小割是否唯一。

解法:在求出最大流的基础上,从源点进行一次搜索,搜索按照未饱和的边进行,得到顶点子集S的顶点个数;再从汇点反向搜索未饱和的边,得到子集T的顶点个数,判定顶点数相加是否等于总共的顶点数。

http://blog.csdn.net/waitfor_/article/details/7330437的文章写的很好,这里截取文中所画的两个图进行说明。

(1)正向搜索集合为S,反向搜索集合为T,cnt1和cnt2都是最小割边。很显然M还存在着最小割边,因为从M到T的残余网络也没有流向T的容量了。

(2)增加E1这部分边的容量将直接导致网络最大流量增加。增加E2和E3则不然。同样M中存在并上E1后为割边的边集。

(3)两条割边完全重合为一条,此时网络中的割边唯一。

 

代码如下:

View Code
#include 
#include
#include
#include
#include
using namespace std;const int SS = 805, TT = 806;const int INF = 0x3fffffff;int N, M, A, B;struct Edge { int v, c, next; };Edge e[30000];int idx, head[810], lv[810];int front, tail, que[810];int vis[810];void insert(int a, int b, int c) { e[idx].v = b, e[idx].c = c; e[idx].next = head[a]; head[a] = idx++;}bool bfs() { memset(lv, 0xff, sizeof (lv)); front = tail = lv[SS] = 0; que[tail++] = SS; while (front < tail) { int u = que[front++]; for (int i = head[u]; i != -1; i = e[i].next) { int v = e[i].v; if (!(~lv[v]) && e[i].c) { lv[v] = lv[u] + 1; if (v == TT) return true; que[tail++] = v; } } } return false;}int dfs(int u, int sup) { if (u == TT) return sup; int tf = 0, f; for (int i = head[u]; i != -1; i = e[i].next) { int v = e[i].v; if (lv[u]+1==lv[v] && e[i].c && (f=dfs(v, min(e[i].c, sup-tf)))) { tf += f; e[i].c -= f, e[i^1].c += f; if (tf == sup) return sup; } } if (!tf) lv[u] = -1; return tf;}void dinic() { int ret = 0; while (bfs()) { ret += dfs(SS, INF); }// printf("ret = %d\n", ret); }void flood(int u, int &cnt) { for (int i = head[u]; i != -1; i = e[i].next) { if (e[i].c && !vis[e[i].v]) { ++cnt; vis[e[i].v] = 1; flood(e[i].v, cnt); } }}void flood_r(int u, int &cnt) { for (int i = head[u]; i != -1; i = e[i].next) { if (e[i^1].c && !vis[e[i].v]) { ++cnt; vis[e[i].v] = 1; flood_r(e[i].v, cnt); } }}bool query() { int cnta = 0, cntb = 0; // 分别为从两个方向进行搜索而计数 memset(vis, 0, sizeof (vis)); vis[SS] = vis[TT] = 1; flood(SS, cnta); memset(vis, 0, sizeof (vis)); vis[SS] = vis[TT] = 1; flood_r(TT, cntb); return cnta + cntb == N;}int main() { while (scanf("%d %d %d %d", &N, &M, &A, &B), N|M|A|B) { int a, b, c; idx = 0; memset(head, 0xff, sizeof (head)); insert(SS, A, INF), insert(A, SS, 0); insert(B, TT, INF), insert(TT, B, 0); for (int i = 0; i < M; ++i) { scanf("%d %d %d", &a, &b, &c); insert(a, b, c), insert(b, a, c); } dinic(); printf(query() ? "UNIQUE\n" : "AMBIGUOUS\n"); } return 0; }

 

你可能感兴趣的文章
P1005
查看>>
std 与标准库
查看>>
Redis入门之一简介
查看>>
spring security3.x学习(13)_第三个例子要使用hsql数据库
查看>>
这里是黑房子开发者社区
查看>>
★思维导图的30个问答
查看>>
Xcode 6更新默认不支持armv7s架构
查看>>
python正则表达式替换函数中的回调函数
查看>>
用python 10min手写一个简易的实时内存监控系统
查看>>
oralce-MD5加密函数
查看>>
Linux下Redis的安装和使用
查看>>
NIO文章翻译
查看>>
html5对于文件的相关操作
查看>>
aerospike和amc安装部署
查看>>
Redis 面试知识点笔记(一)Redis简介
查看>>
thttpd嵌入式web开发笔记
查看>>
Vue.nextTick()
查看>>
分布式系统学习技术点二:Mycat篇二(进阶)
查看>>
python检测主机状态
查看>>
查看windows 中指定端口号
查看>>