zoj 2587 - Unique Attack(网络流’最小割)
2015-05-10 20:57
337 查看
题目:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1587
题意:
N个点,M条无向边,判断从s到t的最小割是否唯一。
思路:
判断最小割是否唯一的方法是:
跑一次最大流,从源点s和汇点t各一次dfs,用一个数组记录经过的点。
两次dfs之后有点未被记录则最小割不唯一。否则唯一。
证明见:http://www.cnblogs.com/ka200812/archive/2011/07/30/2121872.html
AC.
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1587
题意:
N个点,M条无向边,判断从s到t的最小割是否唯一。
思路:
判断最小割是否唯一的方法是:
跑一次最大流,从源点s和汇点t各一次dfs,用一个数组记录经过的点。
两次dfs之后有点未被记录则最小割不唯一。否则唯一。
证明见:http://www.cnblogs.com/ka200812/archive/2011/07/30/2121872.html
AC.
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <queue> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 805; int N, M, L; int vis[maxn]; struct edge { int to, cap, rev, id; edge(int t, int c, int r, int d) { to = t; cap = c; rev = r; id = d; } }; vector<edge> g[maxn]; int level[maxn], iter[maxn]; void addedge(int from, int to, int cap, int id) { g[from].push_back(edge(to, cap, g[to].size(), id)); g[to].push_back(edge(from, 0, g[from].size()-1, id+1)); } void bfs(int s) { memset(level, -1, sizeof(level)); queue<int> que; level[s] = 0; que.push(s); while(!que.empty()) { int v = que.front(); que.pop(); for(int i = 0; i < g[v].size(); ++i) { edge &e = g[v][i]; if(e.cap > 0 && level[e.to] < 0) { level[e.to] = level[v] + 1; que.push(e.to); } } } } int dfs(int v, int t, int f) { if(v == t) return f; for(int &i = iter[v]; i < g[v].size(); ++i) { edge &e = g[v][i]; if(e.cap > 0 && level[v] < level[e.to]) { int d = dfs(e.to, t, min(f, e.cap)); if(d > 0) { e.cap -= d; g[e.to][e.rev].cap += d; return d; } } } return 0; } int max_flow(int s, int t) { int flow = 0; while(1) { bfs(s); if(level[t] < 0) return flow; memset(iter, 0, sizeof(iter)); int f; while((f = dfs(s, t, INF)) > 0) { flow += f; } } } void dfs1(int x) { vis[x] = 1; for(int i = 0; i < g[x].size(); ++i) { edge e = g[x][i]; if(e.id%2==0 && e.cap && !vis[e.to]) dfs1(e.to); } } void dfs2(int x) { vis[x] = 1; for(int i = 0; i < g[x].size(); ++i) { edge e = g[x][i]; if(e.id%2==1 && g[e.to][e.rev].cap && !vis[e.to]) dfs2(e.to); } } int main() { //freopen("in", "r", stdin); int s, t; while(~scanf("%d%d%d%d", &N, &M, &s, &t)) { if(N == 0 && M == 0 && s == 0 && t == 0) break; for(int i = 1; i <= maxn; ++i) g[i].clear(); L = M; for(int i = 0; i < 2*M; i+=2) { int u, v, c; scanf("%d%d%d", &u, &v, &c); addedge(u, v, c, i); addedge(v, u, c, i+2); } int an = max_flow(s, t); //printf("%d\n", an); memset(vis, 0, sizeof(vis)); dfs1(s); dfs2(t); int ok = 0; for(int i = 1; i <= N; ++i) { if(vis[i] == 0) { ok = 1; printf("AMBIGUOUS\n"); break; } } if(!ok) printf("UNIQUE\n"); } return 0; }
相关文章推荐
- zoj 2587 Unique Attack 最小割判定
- 【最小割+判定唯一性】ZOJ-2587 Unique Attack
- zoj 2587 Unique Attack(最小割的唯一性判定)
- ZOJ 2587 Unique Attack 判断最小割是否唯一
- ZOJ 2587 - Unique Attack 最小割,判断割边集是否唯一
- ZOJ 2587 Unique Attack 最小割
- zoj 2587 Unique Attack【最小割】
- ZOJ 2587 Unique Attack 判断最小割是否唯一
- zoj 2587 Unique Attack (判断最小割是否唯一)
- ZOJ-2587 Unique Attack(最小割是否唯一判定)
- zoj 2587 Unique Attack 【判断最小割是否唯一】
- ZOJ 2587 Unique Attack 判最小割唯一
- zoj 2587 Unique Attack 判断最小割是否唯一 sap+dfs
- ZOJ-2587 Unique Attack 最小割的唯一性判定
- ZOJ 2587 && ACdream1235 Unique Attack(判断最小割是否唯一)
- zoj 2587 Unique Attack(判断最小割的唯一性)
- ZOJ 2587 Unique Attack(最小割唯一性判断)
- ZOJ 2587 Unique Attack 判最小割唯一
- ZOJ-2587-Unique Attack(最小割的唯一性)
- ZOJ 2587--Unique Attack【判断最小割是否唯一】