POJ 2125 --Destroying The Graph【最小割解决 "最小点权覆盖问题" && 输出解(割边集) && 各种不懂】
来源:互联网 发布:asm算法源码 编辑:程序博客网 时间:2024/06/10 03:24
Description
Alice assigns two costs to each vertex: Wi+ and Wi-. If Bob removes all arcs incoming into the i-th vertex he pays Wi+ dollars to Alice, and if he removes outgoing arcs he pays Wi- dollars.
Find out what minimal sum Bob needs to remove all arcs from the graph.
Input
Output
Sample Input
3 61 2 34 2 11 21 13 21 23 12 3
Sample Output
531 +2 -2 +
题意:给你一幅有向图, 对于点i删除所有进入该点的边就要支付费用W[i]+(情况1), 删除所有从该点出发的边就要支付费用W[i]-,问删除图中的所有边至少需要多少费用(情况2)。
分析:首先我们根据题意,选点就能删除一些边, 那么这可以看成是“用点去覆盖边”, 这里无非是把边分成了2类,
我们可以把原来的点进行拆点,那么就完完全全等价于“用点去覆盖边",如果支付费用都为1,那么这就是”最小点覆盖集“问题,但这题费用不确定,那么这就是“最小点权覆盖集”问题, 借助二分匹配的思想,我们可以引入“最小割”来解决“最小点权覆盖”问题。
建图:拆点,左点阵为情况2的点, 右点阵为情况1的点,右点阵跟汇点T连流量为W+,左点阵跟源点S连费用W-,
对于输入的边<u, v> 连边 (u, v+n)费用为无穷大inf。跑一边最大流,求出最小费用。
输出解:不理解啊。
void solve(int u){ mark[u] = 1; for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].v; if(edge[i].cap - edge[i].flow > 0 && !mark[v]) solve(v); }}
总结:二分匹配的题都可以用最大流来解,在二分图中 有 “最小点覆盖集”和“最打独立集”,如果有了点权,那么就要用最大流(最小割)来解决 “最小点权覆盖集”(最小割)和“最大点权独立集”(最大流)问题。
以上解析来自http://blog.csdn.net/pi9nc/article/details/27112091
看了别人的解析一下午,对于最小割集的那一块还是不懂, 其他大神还都是用sap写的,sap输出解集和dinic的输出解集的代码还不一样, 而且对最小割不够理解,只能一点一点的调试,试了一下午终于试了出。醉了醉了,理论不扎实,只会用模板的诟病。奋斗奋斗,要理解最大流和最小割 。
#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <cmath>#define maxn 5500#define maxm 1000000#define INF 0x3f3f3f3fusing namespace std;int m, n;int head[maxn],cur[maxn], cnt;int dist[maxn], vis[maxn];int mark[maxn];struct node{ int u, v, cap, flow, next;};node edge[maxm];void init(){ cnt = 0; memset(head, -1, sizeof(head)); memset(mark, 0, sizeof(mark));}void add(int u, int v, int w){ node E1 = {u, v, w, 0, head[u]}; edge[cnt] = E1; head[u] = cnt++; node E2 = {v, u, 0, 0, head[v]}; edge[cnt] = E2; head[v] = cnt++;}void getmap(){ int a, u ,v; for(int i = 1; i <= n; ++i){ scanf("%d", &a); add(i + n, n * 2 + 1, a); } for(int i = 1; i <= n; ++i){ scanf("%d", &a); add(0, i, a); } while(m--){ scanf("%d%d", &u, &v); add(u, v + n, INF); }}bool BFS(int st ,int ed){ queue<int>q; memset(vis, 0 ,sizeof(vis)); memset(dist, -1, sizeof(dist)); vis[st] = 1; dist[st] = 0; q.push(st); while(!q.empty()){ int u = q.front(); q.pop(); for(int i = head[u]; i != -1; i = edge[i].next){ node E = edge[i]; if(!vis[E.v] && E.cap > E.flow){ vis[E.v] = 1; dist[E.v] = dist[u] + 1; if(E.v == ed) return true; q.push(E.v); } } } return false;}int DFS(int x, int ed, int a){ if(x == ed || a == 0) return a; int flow = 0, f; for(int &i = cur[x]; i != -1; i = edge[i].next){ node &E = edge[i]; if(dist[E.v] == dist[x] + 1 && (f = DFS(E.v, ed, min(a, E.cap - E.flow))) > 0){ E.flow += f; edge[i ^ 1].flow -= f; a -= f; flow += f; if(a == 0) break; } } return flow;}int maxflow(int st, int ed){ int flowsum = 0; while(BFS(st,ed)){ memcpy(cur, head, sizeof(head)); flowsum += DFS(st, ed, INF); } return flowsum;}void solve(int u){ mark[u] = 1; for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].v; if(edge[i].cap - edge[i].flow > 0 && !mark[v]) solve(v); }}int main (){ while(scanf("%d%d", &n, &m) != EOF){ init(); getmap(); printf("%d\n", maxflow(0, 2 * n + 1)); solve(0); int ans= 0; for(int i = 1; i <= n; ++i){ if(!mark[i]) ans++; if(mark[i + n]) ans++; } printf("%d\n", ans); for(int i = 1;i <= n; ++i){ if(!mark[i]) printf("%d -\n", i); if(mark[i + n]) printf("%d +\n", i); } } return 0;}
- POJ 2125 --Destroying The Graph【最小割解决 "最小点权覆盖问题" && 输出解(割边集) && 各种不懂】
- poj 2125 Destroying The Graph(最小割,最小点权覆盖)
- POJ 2125 Destroying The Graph 二分图最小点权覆盖 最小割
- POJ 2125 Destroying The Graph 最小点权覆盖
- POJ 2125 Destroying The Graph 最小点权覆盖集
- 【POJ】2125 Destroying The Graph 最小点权覆盖
- poj 2125 Destroying The Graph 最小点权覆盖
- Destroying The Graph (poj 2125 最小点权覆盖)
- poj 2125 Destroying The Graph 最小点权覆盖集
- poj 2125 Destroying The Graph(最小点权覆盖集)
- poj 2125 最小割解决 "最小点权覆盖问题" +输出解(割边集)
- poj 2125 最小割解决 "最小点权覆盖问题" +输出解(割边集)
- ZOJ 2429 Destroying The Graph 最小割(最小点权覆盖)
- POJ 2125 Destroying The Graph (dinic求最小点权覆盖)
- POJ 2125 Destroying The Graph (最小点权覆盖集)
- 【二分图|最小点权覆盖】POJ-2125 Destroying The Graph
- POJ 2125 Destroying The Graph(二分图最小点权覆盖)
- POJ 2125 Destroying The Graph 二分图最小点权覆盖集
- Oracle中当前用户使用另一用户数据库表的方法
- eclipse报错lib32stdc++6
- LaTex: ! LaTeX Error: Unknown graphics extension: .eps 出错处理
- 多属性运动(json)
- Linux下软件包管理-
- POJ 2125 --Destroying The Graph【最小割解决 "最小点权覆盖问题" && 输出解(割边集) && 各种不懂】
- Android Service完全解析,关于服务你所需知道的一切(下)
- Got an error reading communication packets
- iOS CATransform3DMakeRotation 旋转,翻转
- UITableView
- 使用apple script发送邮件
- com.google.gson.JsonSyntaxException
- Hdu 5363 Key Set【快速幂运算】
- C++(4)数组