Vijos1352 NOI2006 最大获利 最小权闭合图

Orz胡伯涛《最小割模型在信息学竞赛中的应用》

建图方法:

设立源点S和汇点T,S和用户(共M个)连边,载流量为满足其要求的获利

T和中转站(共N个)连边,载流量为建立该中转站的费用

每个用户向对应的2个中转站连边,载流量为inf

对该图跑一遍最大流,求出最小割f,(∑Ci)-f就是答案

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <queue>
  5
  6 const int maxV=55005;
  7 const int maxE=155005;
  8 const int inf=0x3f3f3f3f;
  9
 10 struct Edge
 11 {
 12     int to,next;
 13     int capacity;
 14
 15     void assign(int t,int n,int c)
 16         { to=t; next=n; capacity=c; }
 17 };
 18
 19 Edge elist[2*maxE];
 20 int head[maxV];
 21 int ecnt;
 22
 23 void initEdge()
 24 {
 25     memset(head,-1,sizeof(head));
 26     ecnt=0;
 27 }
 28
 29 inline void addEdge(int from,int to,int capacity)
 30 {
 31     elist[ecnt].assign(to,head[from],capacity);
 32     head[from]=ecnt++;
 33     elist[ecnt].assign(from,head[to],0);
 34     head[to]=ecnt++;
 35 }
 36
 37 int N,M;
 38 int tot;
 39 int sink; //1~M:user M+1~N:station
 40
 41 void input()
 42 {
 43     scanf("%d%d",&N,&M);
 44     initEdge();
 45     sink=N+M+1;
 46     int cost;
 47     for(int i=1;i<=N;i++)
 48     {
 49         scanf("%d",&cost);
 50         addEdge(M+i,sink,cost);
 51     }
 52     tot=0;
 53     int v1,v2;
 54     for(int i=1;i<=M;i++)
 55     {
 56         scanf("%d%d%d",&v1,&v2,&cost);
 57         tot+=cost;
 58         addEdge(i,M+v1,inf);
 59         addEdge(i,M+v2,inf);
 60         addEdge(0,i,cost);
 61     }
 62 }
 63
 64 int layer[maxV];
 65 std::queue<int> que;
 66
 67 bool bfs()
 68 {
 69     memset(layer,0,sizeof(layer));
 70     layer[0]=1;
 71     que.push(0);
 72     while(!que.empty())
 73     {
 74         int cur=que.front();
 75         que.pop();
 76         for(int e=head[cur];e!=-1;e=elist[e].next)
 77         {
 78             int& to=elist[e].to;
 79             int& cp=elist[e].capacity;
 80             if(!layer[to] && cp)
 81             {
 82                 layer[to]=layer[cur]+1;
 83                 que.push(to);
 84             }
 85         }
 86     }
 87     return layer[sink];
 88 }
 89
 90 int dfs(int cur,int flow)
 91 {
 92     if(cur==sink) return flow;
 93     int res(0);
 94     for(int e=head[cur];e!=-1;e=elist[e].next)
 95     {
 96         int& to=elist[e].to;
 97         int& cp=elist[e].capacity;
 98         if(layer[to]==layer[cur]+1 && cp)
 99         {
100             int tp=dfs(to,std::min(flow,cp));
101             res+=tp; flow-=tp;
102             elist[e].capacity-=tp;
103             elist[e^1].capacity+=tp;
104             if(!flow) return res;
105         }
106     }
107     return res;
108 }
109
110 int dinic()
111 {
112     int res(0);
113     while(bfs()) res+=dfs(0,inf);
114     return res;
115 }
116
117 int main()
118 {
119     input();
120     printf("%d\n",tot-dinic());
121     return 0;
122 }
时间: 2024-11-05 18:17:44

Vijos1352 NOI2006 最大获利 最小权闭合图的相关文章

bzoj 1497: [NOI2006]最大获利 -- 最小割

1497: [NOI2006]最大获利 Time Limit: 5 Sec  Memory Limit: 64 MB Description 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS&T通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究.站址勘测.最优化等项目.在前期市场调查和站址勘测之后,公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要

【BZOJ1497】[NOI2006]最大获利 最小割

裸的最小割,很经典的模型. 建图:要求总收益-总成本最大,那么将每条弧与源点相连,流量为成本,每个收益与汇点相连,流量为收益,然后每条弧与它所能到达的收益相连,流量为inf. 与源点相连的是未被选中的弧(未花费的成本),与汇点相连的是选中的收益,那么,初始状态是完美的,显然不可能,因为获得收益必然要花费成本,所以每条源汇点相连的路中必须去掉一条,那么最小割就是最小的(选中的成本和未选的收益的和),每条增广路都是一种抵消,用总收益减去就是最终的选中收益和. 而最小割就是最大流.证明看论文= =.

最大权闭合图 &amp;&amp; 【BZOJ】1497: [NOI2006]最大获利

最大权闭合图详细请看胡伯涛论文<最小割模型在信息学竞赛中的应用>,我在这里截图它的定义以及一些东西. 假设我们有一个图,点集的出边都是连到点集的,那么称这个为闭合图.现在这些点集都有个权值,我们要选择某个闭合图使得权值最大. 回到此题: 最大获利这一题,我们可以这样看,用户群和中转站为带权的点集,用户群的权为收益,中转站的权为负的成本,即0-成本,用户群向其中两个中转站连弧,那么这个就是一个闭合图. 我们要求这个闭合图的权值和最大,即最大收益,那么就能转移到上面的求最大权闭合图的做法去了. 做

BZOJ_1497_[NOI2006]_最大获利(最大流+最大权闭合图)

描述 共n个站点,给出建立每个站点所需要的花费.现在有m个客户需要开通服务,每个客户需要有两个站点,客户给钱.问最大利润是多少. 分析 要选一个客户,就必须要选他所需的两个站点,这样有约束关系的,可以用最大权闭合图做. 胡伯涛的论文<最小割模型在信息学竞赛中的应用>: http://wenku.baidu.com/link?url=AwU_F4lYPSxxzmOrAZpL0t6lCMWjIVbuAXI59EKPbqEj7gpw0VRhhrGDU4BbOVFNGlVRt0KLZ6QrCAszJI

BZOJ 1497 JZYZOJ 1344 [NOI2006]最大获利 网络流 最大权闭合图

http://www.lydsy.com/JudgeOnline/problem.php?id=1497 http://172.20.6.3/Problem_Show.asp?id=1344 思路:(最大权闭合图的思路相同) 将所有的用户群获利(正值)作为一个点连一条权值为获利值的边到st点,将所有的建站消耗(输入的是正值但是是在获利中减去的所以实质还是负值)作为一个点连一条权值为消耗值的边到ed点,再将每个用户群点和其依赖的建站点连一条权值为无穷的边,求st到ed的最大流. 此时,所求的最大获

noi 2006 最大收益 最大权闭合图转最小割转最大流

题意:一个公司有n个可以建造通讯战的地方,建造成本分别为pi,然后第i个公司会选择使用通讯站ai与bi,使用费用是ci,然后问这个通讯公司怎么建站能够获利最大.(净获利=总收益-总成本): 网上看到一篇题解,直接说这是个最小割,求最小割然后总收益-最小割就是了.这种题解就是一点用也没有,为什么是最小割,总得解释解释吧,撂下结论就跑了,这种题解写来何用. 之后查了一篇国家集训队的论文<最小割模型在信息学竞赛中的应用>才明白原来是最大权闭合图转的最小割,至于为什么能转成最小割,自己去看论文的证明吧

HDU 4971 A simple brute force problem.(最小割,最大权闭合图)

http://acm.hdu.edu.cn/showproblem.php?pid=4971 A simple brute force problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 182    Accepted Submission(s): 115 Problem Description There's a com

最大权闭合图 最小割

闭合图为原图的一个子图, 满足任意一个节点的后继仍在闭合图中. 给原图的每个点以一个点权, 权值总和最大的闭合图称为最大权闭合图. 我们考虑利用最小割求解最大权闭合图. 首先, 为了权值最大, 我们贪心地将所有点权为正的点给选上, 但是这样可能会矛盾, 因为一个点权为正的点的后继可能点权为负. 我们考虑利用最小割, 减去最小的使方案合法的花费. 建立源点 S , 与 S 相连的意义是这个点被选择, 则初始的时候, 对于点权为正的点 i , 连边 (S, i, a[i]) . 建立汇点 T , 与

OpenJudge 3765(最大权闭合图,最小割

题目大意:需要解雇若干人,解雇每个人有一个损失或收益,解雇一个人就必须结果他的所有下属,问最大收益. 思路:裸最大权闭合图问题,对于权值为q的点,负权向汇点连-p的边,正权源点向其连p的边,上下级关系上级向下级连oo的边,然后求最大流最小割,最大收益即为总正点权减最小割,需要裁员的人即为残余图中从源点可达的点. 参考:http://blog.csdn.net/scorpiocj/article/details/6085637 #include <bits/stdc++.h> #define p