hdu3879 最大权闭合图
2015-10-28 21:58
357 查看
若a,b 2点能够相连,那么可以得到ci的价值,也就是说a,b是得到c的前提条件,对于每一个点,又有耗费。
对于本题,先求出最多能够得到的利益有多少,最小割=未被 选的用户的收益之和 + 被选择的站点的成本之和,要尽量的小。
分析:
把每个用户和每个站点都看成一个顶点。建立网络,从源点S向每个用户连接一条容量为收益的有向边,每个用户向相关的两个站点连接一条容量为无穷大的 有向边,每个站点向汇点T连接一条容量为成本的有向边。求出网络最小割集的容量就是Maxflow=(未被选的用户的收益之和 + 被选择的站点的成本之和)。设Total为所有用户的收益之和,我们要求的是(被选的用户的收益之和 – 被选择的站点的成本之和),恰好等于Total – Maxflow,就是最大收益。
为什么是这样的?因为任何一个可行割集对应了一个满足条件的方案,具体来说被选择的顶点就是S集合中的顶点,而割集对应了cut=(未被 选的用户的收益之和 + 被选择的站点的成本之和),我们为了要求的(被选的用户的收益之和 – 被选择的站点的成本之和)= Total – cut尽量大,Total一定,所以要让cut尽量小,直至最小割集。
对于本题,先求出最多能够得到的利益有多少,最小割=未被 选的用户的收益之和 + 被选择的站点的成本之和,要尽量的小。
#include<stdio.h> #include<string.h> #include<queue> #define INF 99999999 using namespace std; const int maxn = 61000; struct node { int to; int v; int flag; int next; }edge[500001]; int pre[maxn],index,vis[maxn],S,T; int min(int x,int y){return x<y?x:y;} void add(int x,int y,int z) { edge[index].to=y; edge[index].v=z; edge[index].flag=index+1; edge[index].next=pre[x]; pre[x]=index++; edge[index].to=x; edge[index].v=0; edge[index].flag=index-1; edge[index].next=pre[y]; pre[y]=index++; } int dfs(int u,int low) { int i,used=0; if(u==T) return low; for(i=pre[u];i!=-1&&used<low;i=edge[i].next) { if(vis[edge[i].to]==vis[u]+1&&edge[i].v>0) { int a=dfs(edge[i].to,min(edge[i].v,low-used)); if(!a)continue; edge[i].v-=a; edge[edge[i].flag].v+=a; used+=a; } } if(!used) vis[u]=-1; return used; } bool BFS() { memset(vis,-1,sizeof(vis)); queue<int>q; int i; vis[0]=0; q.push(0); while(!q.empty()) { int t=q.front(); q.pop(); for(i=pre[t];i!=-1;i=edge[i].next) { if(edge[i].v&&vis[edge[i].to]<0) { vis[edge[i].to]=vis[t]+1; q.push(edge[i].to); } } } if(vis[T]>0) return true; return false; } int main() { int n,m,s,t,i; while(~scanf("%d%d",&n,&m)) { index=1; memset(pre,-1,sizeof(pre)); for(i=1;i<=n;i++) { int x; scanf("%d",&x); add(0,i,x); } int sum=0; for(i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,n+i,INF); add(y,n+i,INF); add(n+i,n+m+1,z); sum+=z; } int ans=0; S=0,T=n+m+1; while(BFS()) { int a=dfs(0,INF); if(!a)break; ans+=a; } printf("%d\n",sum-ans); } }
分析:
把每个用户和每个站点都看成一个顶点。建立网络,从源点S向每个用户连接一条容量为收益的有向边,每个用户向相关的两个站点连接一条容量为无穷大的 有向边,每个站点向汇点T连接一条容量为成本的有向边。求出网络最小割集的容量就是Maxflow=(未被选的用户的收益之和 + 被选择的站点的成本之和)。设Total为所有用户的收益之和,我们要求的是(被选的用户的收益之和 – 被选择的站点的成本之和),恰好等于Total – Maxflow,就是最大收益。
为什么是这样的?因为任何一个可行割集对应了一个满足条件的方案,具体来说被选择的顶点就是S集合中的顶点,而割集对应了cut=(未被 选的用户的收益之和 + 被选择的站点的成本之和),我们为了要求的(被选的用户的收益之和 – 被选择的站点的成本之和)= Total – cut尽量大,Total一定,所以要让cut尽量小,直至最小割集。
相关文章推荐
- 优化斐波那契
- Android之React Native平台与Android本地模块之间的调用
- 谈业务流程全生命周期管理支撑业务流程再造(3)
- 关于Android Studio 中快捷键 相当于 Eclipse中 Alt+/ 怎么设置
- 决策树算法 生成 剪枝 in Python
- 一个大三的物联网专业学生的想法法
- OD调试篇11
- Python中变量作用域问题——局部变量与全局变量
- LeetCode 144: Binary Tree Preorder Traversal
- 读数据库,写文件
- hdu 4639 Hehe(斐波那契)
- innodb数据库 OPTIMIZE TABLE 提示Table does not support optimize, doing recreate + analyze instead 分类: My
- django下video播放时间不能超过5s并且视频有时无法显示问题的解决方法
- android技术学习资源及学习途径
- 原型
- 加班引发的感想
- 如何计算时间复杂度
- 数据类型转换
- cocoaPods
- JVM内存参数详解以及配置调优