Uva-10480 Sabotage
2015-09-09 20:03
561 查看
题目链接:Sabotage
题目大意:求s与t点之间消除哪些边使s与t不相连且所删除的边的权值和最小。
解题思路:这道题其实是求最小割的边集,由于最小割等于最大流,所以跑一遍Dinic就可以得到最小权值和,但是如何求最小割的边集呢?我们把最后的残余网络找到,会发现那些最小权值且能使s与t联通的边权已经变为了0,那么我们就可以把与s点相连且相连边的权不为零的点集找到,再把这些点相连的且边权为零的边找到,即为所求答案。
代码如下:
题目大意:求s与t点之间消除哪些边使s与t不相连且所删除的边的权值和最小。
解题思路:这道题其实是求最小割的边集,由于最小割等于最大流,所以跑一遍Dinic就可以得到最小权值和,但是如何求最小割的边集呢?我们把最后的残余网络找到,会发现那些最小权值且能使s与t联通的边权已经变为了0,那么我们就可以把与s点相连且相连边的权不为零的点集找到,再把这些点相连的且边权为零的边找到,即为所求答案。
代码如下:
#include <map> #include <set> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; typedef pair<int, int> P; const int inf = 0x3f3f3f3f; const int maxn = 100 + 15; const int maxm = 1e6 + 15; struct Edge { int to, cap, next; }; int ecnt, st, ed, m, n; Edge es[maxm]; int cur[maxn], dep[maxn], head[maxn], vis[maxn]; class Dinic { public: void init(){ memset(head, -1, sizeof head); ecnt = 0; } void add_edge(int u, int v, int cap) { es[ecnt].to = v; es[ecnt].next = head[u]; es[ecnt].cap = cap; head[u] = ecnt++; } void add_double(int u, int v, int w1, int w2 = 0) { add_edge(u, v, w1); add_edge(v, u, w2); } bool BFS() { queue<int> q; q.push(st); memset(dep, 0x3f, sizeof dep); dep[st] = 0; while(q.size() && dep[ed] == inf) { int u = q.front(); q.pop(); for(int i = head[u]; ~i; i = es[i].next) { Edge& e = es[i]; if(e.cap > 0 && dep[e.to] == inf) { dep[e.to] = dep[u] + 1; q.push(e.to); } } } return dep[ed] < inf; } int DFS(int u, int maxflow) { if(u == ed) return maxflow; int res = 0; for(int i = cur[u]; ~i; i = es[i].next) { Edge& e = es[i]; if(dep[e.to] == dep[u] + 1 && e.cap > 0) { int flow = DFS(e.to, min(maxflow, e.cap)); cur[u] = i; res += flow; maxflow -= flow; es[i].cap -= flow; es[i ^ 1].cap += flow; if(!maxflow) return res; } } dep[u] = inf; return res; } ll MaxFlow(){ ll ans = 0; while(BFS()) { for(int i = st; i <= ed; i++) cur[i] = head[i]; ans += DFS(st, inf); } return ans; } }; inline int read() { char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return x; } int main(){ #ifdef NEKO freopen("Nya.txt", "r", stdin); #endif Dinic dic; while(scanf("%d%d", &n, &m) != EOF && n + m) { st = 0, ed = n + 1; dic.init(); dic.add_double(st, 1, inf); dic.add_double(2, ed, inf); for(int i = 1; i <= m; i++) { int u, v, w; u = read(); v = read(); w = read(); dic.add_double(u, v, w, w); } dic.MaxFlow(); set<int> sp; vector<P> ans; queue<int> que; que.push(st); while(que.size()) { int u = que.front(); que.pop(); sp.insert(u); for(int i = head[u]; ~i; i = es[i].next) { int v = es[i].to; if(es[i].cap && !sp.count(v)) { sp.insert(v); que.push(v); } } } que.push(st); memset(vis, 0, sizeof vis); while(que.size()) { int u = que.front(); que.pop(); vis[u] = 1; for(int i = head[u]; ~i; i = es[i].next) { int v = es[i].to; if(!es[i].cap && !sp.count(v)) ans.push_back(P(u, v)); else if(!vis[v]) { vis[v] = 1; que.push(v); } } } sort(ans.begin(), ans.end()); ans.resize(unique(ans.begin(), ans.end()) - ans.begin()); for(int i = 0; i < ans.size(); i++) printf("%d %d\n", ans[i].first, ans[i].second); puts(""); } return 0; }
相关文章推荐
- @property 属性理解
- Android的进程Hnadler与AsyncTask
- 第五章 初始化与清理(上)
- UIView
- latex 下划线
- 【leetcode每日一题】104.Maximum Depth of Binary Tree
- CentOS用DD镜像及恢复过程
- 三步搞定浏览器
- 在Unity3D中控制动画播放
- 按时间排序返回前十条数据且不重复
- leetcode9 Palindrome Number
- 网站性能优化
- ARC,MRC理解
- 屌屌的Web树--保存分类
- 写一个网络图片查看器
- 神经网络
- Qt5 中使用了QQuickWidget,程序退出时容易崩溃的解决办法。
- lesson3 -Vim
- 引导页的铺设
- Java简单彩票系统(35选7)