POJ 2987 Firing 【最大权闭合图】
来源:互联网 发布:linux监控tomcat进程 编辑:程序博客网 时间:2024/05/21 18:42
POJ 2987 题目链接
题意:
公司要进行裁员,裁掉一个人可以获得一定的利益或损失(用正数和负数表示)。
一些人之间有附属关系,比如b是a的下属,则裁掉a就必须裁掉b。
问要取得最大的利益,最少要裁掉几个人,取得的最大利益是多少
结论一:最大权闭合图的的权=原图中权值为正的点的和 - 最小割(最大流)
结论二:最小割对应取点方案就是最小取点数
具体详细证明过程 请参考:胡伯涛的论文《最小割模型在信息学竞赛中的应用》链接
大佬的证明:
结论一:
首先引入结论,最小割所产生的两个集合中,其源点S所在集合(除去S)为最大权闭合图,接下来我们来说明一些结论。
证明:最小割为简单割。
引入一下简单割的概念:割集的每条边都与S或T关联。(请下面阅读时一定分清最小割与简单割,容易混淆)
那么为什么最小割是简单割呢?因为除S和T之外的点间的边的容量是正无穷,最小割的容量不可能为正无穷。所以,得证。
证明网络中的简单割与原图中闭合图存在一一对应的关系。(即所有闭合图都是简单割,简单割也必定是一个闭合图)。
证明闭合图是简单割:如果闭合图不是简单割(反证法)。那么说明有一条边是容量为正无穷的边,则说明闭合图中有一条出边的终点不在闭合图中,矛盾。
证明简单割是闭合图:因为简单割不含正无穷的边,所以不含有连向另一个集合(除T)的点,所以其出边的终点都在简单割中,满足闭合图定义。得正。
证明最小割所产生的两个集合中,其源点S所在集合(除去S)为最大权闭合图。
首先我们记一个简单割的容量为C,且S所在集合为N,T所在集合为M。
则C=M中所有权值为正的点的权值(即S与M中点相连的边的容量)+N中所有权值为负的点权值的绝对值(即N中点与T中点相连边的容量)。记(C=x1+y1);(很好理解,不理解画一个图或想象一下就明白了)。
我们记N这个闭合图的权值和为W。
则W=N中权值为正的点的权值-N中权值为负的点的权值的绝对值。记(W=x2-y2);
则W+C=x1+y1+x2-y2。
因为明显y1=y2,所以W+C=x1+x2;
x1为M中所有权值为正的点的权值,x2为N中权值为正的点的权值。
所以x1+x2=所有权值为正的点的权值之和(记为TOT).
所以我们得到W+C=TOT.整理一下W=TOT-C.
到这里我们就得到了闭合图的权值与简单割的容量的关系。
因为TOT为定值,所以我们欲使W最大,即C最小,即此时这个简单割为最小割,此时闭合图为其源点S所在集合(除去S)。得正。
至此,我们就将最大权闭合图问题转化为了求最小割的问题。求最小割用最小割容量=最大流,即可将问题转化为求最大流的问题。
结论二:
下面证明最小割对应取点方案就是最小取点数
由于原图是个DAG图,所以对于取得的最大权闭合图K,取它的任意一个子图G,如果从K-G仍然是一个闭合图,那么的点权和一定大于等于0,例如:1->2,2->3,1->4,4->5,若最大权闭合图为:{1,2,3,4,5},那么其中任一满足条件的G({1},{1,2},{1,2,3},{1,4},{1,4,5})点权和一定大于等于0,否则去除G,K-G仍然为闭合图,但是K-G的点权和会大于K
所以如果有两种取点方式使得权值相同,但是取点数不同的话,那么肯定存在一个可以移除的满足条件的子图G,其点权和为0
下面考虑构造的网络,对于G在网络中的对应图G',由于在网络求的是最小割,即最大流,而且G的点权和为0,所以G'中与源点S连边的容量和等于G'中与汇点T连边的流量和,同时由于去除G后K还是一个闭合图,所以只有可能G'中的流量流入K'-G',不可能有流量从K'-G'流入G',所以G'的边中除了流量为inf的那些,一定是满流的
再考虑在残留网络中求出取点集的方法,从源点开始floodfill,忽略满流边,即残留网络中的0流边,可以遍历到的点就是要取的点集了,这个道理想一下简单割和闭合图的取法一一对应就可以了
那么G'既然是满流的,在残留网络中就不可能对这些0流边进行处理,那就不会取到G中的点进入取点集,所以建立网络求得得最小割对应的取法取出的就是最小的点数了
(求点方法二:
再回到本题,第二问求最大利益,显然就是最大权闭合图。
第一问问最少裁掉几个人,我采用的是边权放大的方法:
所有上述3中的边扩大一个很大的倍数k,再减去1,所有上述4中的边扩大同样k倍,再加上1。
设num为一共减去了多少个1,则(maxflow + num) / k仍是最大权闭合图的权,而(maxFlow + num) % k就是第一问的答案。
)代码
#include<cstring>#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<queue>using namespace std;const long long INF=1e16;const int INFF=0x3f3f3f3f;struct edge{ int to,rev; long long cap; edge(int x,long long y,int z) { to=x;cap=y;rev=z; }};vector<edge> g[5111];int level[5555],iter[5555],n,m,s;long long sum;bool vis[5555];void add(int from,int to,int cap){ g[from].push_back(edge(to,cap,g[to].size())); g[to].push_back(edge(from,0,g[from].size()-1));}void bfs(int s){ memset(level,-1,sizeof(level)); level[s]=0; queue<int> que; 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); } } }}long long dfs(int v,int t,long long 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[e.to]>level[v]) { long long 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;}long long max_flow(int s,int t){ long long flow=0; while(1) { bfs(s); if(level[t]<0)return flow; memset(iter,0,sizeof(iter)); long long f; while((f=dfs(s,t,INF))>0) { flow+=f; } }}int dfs1(int u){ vis[u]=true; s++; for(int v=0;v<g[u].size();v++) { edge &e=g[u][v]; if(e.cap>0&&!vis[e.to]) { vis[e.to]=true; dfs1(e.to); } }}int main(){ int x,y; while(scanf("%d%d",&n,&m)!=EOF) { for(int i=0;i<=n+1;i++) g[i].clear(); sum=0; long long xx; for(int i=1;i<=n;i++) { scanf("%d",&x); xx=xx*10000; if(x>0) { add(0,i,x); sum+=x; } else add(i,n+1,-x); } for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y,INF); } long long ans=sum-max_flow(0,n+1); s=-1; memset(vis,false,sizeof(vis)); dfs1(0); printf("%d %I64d\n",s,ans); } return 0;}
- poj 2987 Firing ------最大权闭合图
- poj 2987 Firing(最大权闭合图)
- POJ 2987 Firing (最大权闭合图)
- POJ 2987 Firing 最大权闭合图
- poj 2987 Firing 最大权闭合图
- POJ 2987 Firing 最大权闭合图
- POJ 2987 Firing 最大权闭合图
- poj 2987 Firing 最大权闭合图
- POJ 2987 Firing 【最大权闭合图】
- POJ 2987 Firing(最大权闭合)
- POJ 2987 Firing(最大权闭合)
- poj Firing(最大权闭合图)
- POJ 2987 Firing (最大权闭合子图Dinic)
- poj 2987 Firing 最大权闭合图 网络流
- 【POJ】2987 Firing 最大权闭合子图
- POJ 2987 Firing (最大权闭合图,最小割)
- POJ 2987 Firing 最大权闭合子图
- poj 2987 Firing 最大权闭合子图
- POJ 2481 Cows (树状数组)
- C++ 一些知识点
- solr检索建议
- Codeforces 264 (Div. 2) D. Gargari and Permutations
- 在iframe获取父窗口dom对象,iframe加载完毕后触发事件,父页面调用iframe方法
- POJ 2987 Firing 【最大权闭合图】
- OutOfMemoryError系列(1): Java heap space
- 2017暑期ACM俱乐部个人训练赛第4场 G题和J题
- activity工作流多实例并发绘图工具类
- COJ1974-神奇药水
- 分组统计之facet
- hdu1698(线段树区间更新模板)
- 1546: 回形取数
- 链接收藏2