Destroying The Graph 最小点权集--最小割--最大流
Destroying The Graph
构图思路:
1.将所有顶点v拆成两个点, v1,v2
2.源点S与v1连边,容量为 W-
3.v2与汇点连边,容量为 W+
4.对图中原边( a, b ), 连边 (a1,b2),容量为正无穷大
则该图的最小割(最大流)即为最小花费。
简单证明: 根据ST割集的定义,将顶点分成两个点集。所以对于原图中的边(a,b),转换成 S->a1->b2->T. 则此时路径必定存在
一条割边,因为a1->b2为无穷大,所以割边必定是 S->a1 or b2->T, 若为前者则意味着删除a顶点的W-,后者则是b顶点的W+.
所以该图最小割即为最小花费。
计算方案: 对于构图后跑一次最大流,然后对于残留网络进行处理,首先从源点S出发,标记所有能访问到的顶点,这些顶点即为S割点集中
的顶点。 其他则为T集合中顶点, 然后从所有边中筛选出( A属于S,B属于T,且(A,B)容量为0 )的边,即为割边。因为我们的W+/W-边都只有一条,
且都分开了。比较容易处理。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <stack> 11 #include <queue> 12 #include <sstream> 13 #include <iomanip> 14 using namespace std; 15 typedef long long LL; 16 const int INF = 0x4fffffff; 17 const double EXP = 1e-5; 18 const int MS = 2005; 19 const int SIZE = 100005; 20 21 struct edge 22 { 23 int v,c,f,other; 24 }e; 25 26 vector<edge> edges[MS]; // 邻接表 27 vector<int> level_edges[MS]; 28 vector<int> ans; 29 30 int que[MS],level[MS],pre[MS],hash[MS],d[MS]; 31 int s,t; 32 33 void add(int u,int v,int c) 34 { 35 e.v=v; 36 e.c=c; 37 e.f=0; 38 e.other=edges[v].size(); 39 edges[u].push_back(e); 40 41 e.v=u; // reverse edge 42 e.c=0; 43 e.f=0; 44 e.other=edges[u].size()-1; 45 edges[v].push_back(e); 46 } 47 48 bool BFS() // bfs 构建层次网络 49 { 50 int head=0,tail=0,cur,i; 51 for(int i=s;i<=t;i++) 52 level_edges[i].clear(); 53 memset(level,0xff,sizeof(level)); 54 que[tail++]=s; 55 level[s]=0; 56 while(head<tail) 57 { 58 cur=que[head++]; 59 for(i=0;i<edges[cur].size();i++) 60 { 61 e=edges[cur][i]; 62 if(e.c>e.f) 63 { 64 if(level[e.v]==-1) 65 { 66 que[tail++]=e.v; 67 level[e.v]=level[cur]+1; 68 } 69 if(level[e.v]==level[cur]+1) 70 { 71 level_edges[cur].push_back(i); 72 } 73 } 74 } 75 } 76 if(level[t]!=-1) 77 return 1; 78 else 79 return 0; 80 } 81 82 83 int dinic() 84 { 85 int i,j,ans=0,len; 86 while(BFS()) 87 { 88 memset(hash,0,sizeof(hash)); 89 while(!hash[s]) 90 { 91 d[s]=INF; 92 pre[s]=-1; 93 for(i=s;i!=t&&i!=-1;i=j) 94 { 95 len=level_edges[i].size(); 96 while(len&&hash[ edges[i][level_edges[i][len-1]].v] ) 97 { 98 level_edges[i].pop_back(); 99 len--; 100 } 101 if(!len) 102 { 103 hash[i]=1; 104 j=pre[i]; 105 continue; 106 } 107 j=edges[i][level_edges[i][len-1]].v; 108 pre[j]=i; 109 d[j]=min(d[i],edges[i][level_edges[i][len-1]].c-edges[i][level_edges[i][len-1]].f); 110 } 111 if(i==t) 112 { 113 ans+=d[t]; 114 while(i!=s) 115 { 116 j=pre[i]; 117 len=level_edges[j][level_edges[j].size()-1]; 118 edges[j][len].f+=d[t]; 119 if(edges[j][len].f==edges[j][len].c) 120 level_edges[j].pop_back(); 121 edges[i][edges[j][len].other].f-=d[t]; 122 i=j; 123 } 124 } 125 } 126 } 127 return ans; 128 } 129 130 void DFS(int u) 131 { 132 int i,k; 133 hash[u]=1; 134 for(i=0;i<edges[u].size();i++) 135 { 136 k=edges[u][i].v; 137 if(!hash[k]&&edges[u][i].c-edges[u][i].f>0) 138 DFS(k); 139 } 140 } 141 142 int main() 143 { 144 int n,m,i,j,k,N,tmp,answer; 145 while(scanf("%d%d",&n,&m)!=EOF) 146 { 147 N=2*n+1; 148 s=0; 149 t=N; 150 for(i=s;i<=t;i++) 151 edges[i].clear(); 152 for(i=1;i<=n;i++) 153 { 154 scanf("%d",&tmp); 155 add(n+i,N,tmp); 156 } 157 for(i=1;i<=n;i++) 158 { 159 scanf("%d",&tmp); 160 add(0,i,tmp); 161 } 162 for(k=0;k<m;k++) 163 { 164 scanf("%d%d",&i,&j); 165 add(i,n+j,INF); 166 } 167 answer=dinic(); 168 memset(hash,0,sizeof(hash)); 169 DFS(0); 170 ans.clear(); 171 for(i=1;i<=n;i++) 172 { 173 if(!hash[i]) 174 ans.push_back(i); 175 if(hash[n+i]) 176 ans.push_back(n+i); 177 } 178 printf("%d\n%d\n",answer,ans.size()); 179 for(i=0;i<ans.size();i++) 180 { 181 if(ans[i]<=n) 182 printf("%d -\n",ans[i]); 183 else 184 printf("%d +\n",ans[i]-n); 185 } 186 } 187 return 0; 188 }
转载于:https://www.cnblogs.com/767355675hutaishi/p/4437906.html
Destroying The Graph 最小点权集--最小割--最大流相关推荐
- POJ 2125 Destroying The Graph Acwing 2325. 有向图破坏(拆点+最小权点覆盖集)
原题链接 POJ 2125:Destroying The Graph Acwing 2325:有向图破坏 题目大意 我们要删除一个有向图中的所有边,有两种删法,一是删除某点的所有入边,二是删除某点的所 ...
- 最小点权覆盖集最大点权独立集
最小点权覆盖集 最小点权覆盖集解决的是这样一个问题: 在二分图中,对于每条边,两个端点至少选一个,求所选取的点最小权值和. 方法: 1.先对图二分染色,对于每条边两端点的颜色不同 2.然后建立源点S, ...
- 734. [网络流24题] 方格取数问题 二分图点权最大独立集/最小割/最大流
«问题描述: 在一个有m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任 意2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法. «编程任务: 对于给定 ...
- 并查集——最小连接路径和Kruskal(hdu1301)
*没听说过并查集的同学先移步看一下上篇博客http://blog.csdn.net/sm9sun/article/details/53256232 好,首先说一下并查集的标准定义: 概述: 在一些有N ...
- POJ 3308 Paratroopers (对数转换+最小点权覆盖)
题意 敌人侵略r*c的地图.为了消灭敌人,可以在某一行或者某一列安置超级大炮.每一个大炮可以瞬间消灭这一行(或者列)的敌人.安装消灭第i行的大炮消费是ri.安装消灭第j行的大炮消费是ci现在有n个敌人 ...
- 网络流之最小点权覆盖和最大点权独立集学习
转载:http://yzmduncan.iteye.com/blog/1149057 二分图最小点覆盖和最大独立集都可以转化为最大匹配求解.在这个基础上,把每个点赋予一个非负的权值,这两个问题就转化为 ...
- 贪心法求树的最小支配集,最小点覆盖,最大独立集
原文地址(转自 Ashly的博客) 定义: 最小支配集:对于图G = (V, E) 来说,最小支配集指的是从 V 中取尽量少的点组成一个集合, 使得 V 中剩余的点都与取出来的点有边相连.也就是说,设 ...
- [学习笔记]最小割之最小点权覆盖最大点权独立集
最小点权覆盖 给出一个二分图,每个点有一个非负点权 要求选出一些点构成一个覆盖,问点权最小是多少 建模: S到左部点,容量为点权 右部点到T,容量为点权 左部点到右部点的边,容量inf 求最小割即可. ...
- The Minimum Cycle Mean in a Digraph 《有向图中的最小平均权值回路》 Karp
文件链接 Karp在1977年的论文,讲述了一种\(O(nm)\)的算法,用来求有向强连通图中最小平均权值回路(具体问题请参照这里) 本人翻译(有删改): 首先任取一个节点 \(s\) ,定义 \(F ...
最新文章
- programcreek
- html怎么显示直线,html怎么用鼠标画出一条直线,鼠标移动时候要能看到线条
- 50万数据生成6位数不重复字符串_JAVA技术分享:单号的生成
- abap oo 语法
- 截至2018年,目前,企业主流的消息中间件有哪些?各有什么优缺点?面试常问 RabbitMQ使用较多
- TCP UDP 本地套接字 网络套接字
- 视频图像标准:D1/D2/D3/D4/D5
- asp.net WEB 调用 CuteFTP8.0 ftpte.exe 实现大文件上传
- 梦想近在眼前却遥不可及
- 谷歌浏览器fash弹框的设置
- 顺丰android架构师,顺丰数据库运维架构.pdf
- cz73 读取速度慢_【闪迪 Ultra Flair 酷铄 CZ73 闪存盘使用总结】速度|读取|写入|手感_摘要频道_什么值得买...
- 云呐|固定资产条码管理系统的应用实例
- 大津二值化算法(Otsu)
- 华为慧通真相--关联企业迷局
- 容器化技术(十一):Kubernetes中Pod的调度策略-标签与污点实战
- centos屏保“黑客帝国”
- 我的互联网方法论周鸿祎
- 网络安全有多重要 一
- c语言哑铃,一对哑铃也能虐出C罩杯大胸肌!