题意:给定一个无向图,要求判定分离两个点的最小割是否唯一。
解法:在求出最大流的基础上,从源点进行一次搜索,搜索按照未饱和的边进行,得到顶点子集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 <cstdlib> #include <cstring> #include <cstdio> #include <iostream> #include <algorithm> 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; }