题意:给出一个有向图,选择一个点,则要选择它的可以到达的所有节点。选择每个点有各自的利益或损失。求最大化的利益,以及此时选择人数的最小值。

算法:构造源点s汇点t,从s到每个正数点建边,容量为利益。每个负点到t建边,容量为损失的绝对值。其他关系边容量正向无穷,反向0。正数点总和减去最小割即为最大权闭合图答案。因为残余网络不会对0流边处理,所以不会将0流点选入取点集,所以最小割的取法中为被选中的点。

最大权闭合图的求解方法:

  1. 先构造网络流N,添加源点s,从s到正权值点做一条边,容量为点的权值。

  2. 添加汇点t,从负权值点到t做一条边,容量为点的权值的绝对值。

  3. 原来的边的容量统统设为无穷大。比如:

    转换为

  4. 求解最小割:最大权=正权值之和-最小割权值

  5. 残余网络中的点的个数即为裁员个数。

思路:最大权闭合图。用Dinic求最小割

要得到最大收益,就是尽量选择更多收益为正数的人,选择更少收益为负数的人,因此我们将收益为正数的人与源点连一条边,将收益为负数的人与汇点连一条边,这样得到的割集就是未选择的收益为正数的人+选择的收益为负数的人(也可以是损失的收益),要使这个割集越小越好,那么就是求最小割。最大收益是所有正数的和sum,再用sum-最小割(损失的收益)就可以得到最大收益。

最少的裁员人数,最小割后的的残余网络中,只要能从S遍历到的点,就可以看成是被裁掉的点,因为最终肯定会遇到割边达不到T,所以我们直接DFS残余网络的点数就可以得到最少的裁员人数了。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef long long LL; const LL INF = 0x3f3f3f3f3f3f3f3f; struct edge
{
edge(int _v,int _r, LL _c):v(_v),r(_r),c(_c){};
int v,r;
LL c;
}; vector<edge> e[]; void add_edge(int u,int v,LL c)
{
e[u].push_back(edge(v,e[v].size(),c));
e[v].push_back(edge(u,e[u].size()-,));
} int level[];
int iter[]; // 当前弧,在其之前的边已经没有用了
queue<int> q; bool bfs(int s,int t)
{
memset(level,, sizeof(level));
while (!q.empty()) q.pop();
q.push(s);
level[s]=;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=;i<e[u].size();i++)
{
int v=e[u][i].v;
if(e[u][i].c>&&!level[v])
{
q.push(v);
level[v]=level[u]+;
}
if(level[t])return ;
}
}
return ;
} LL dfs(int s,int t, LL flow)
{
if(s==t)return flow;
for(int& i = iter[s];i<e[s].size();i++) // 一次增广返回时,记录当前弧
{
int v = e[s][i].v;
if(e[s][i].c>&&level[v]==level[s]+)
{
LL k = dfs(v,t,min(flow,e[s][i].c));
if(k>)
{
e[s][i].c-=k;
e[v][e[s][i].r].c+=k;
return k;
}
}
}
return ;
} LL Dinic(int s,int t)
{
LL flow=;
while(bfs(s,t))
{
LL f=;
memset(iter, , sizeof(iter));
while((f=dfs(s,t,INF))>)flow+=f;
}
return flow;
} bool vis[];
int cnt;
void GaoCnt(int u)//dfs统计残余图的正边
{
++cnt;
vis[u]=;
for(int i=;i<e[u].size();i++)
{
int v=e[u][i].v;
if(e[u][i].c>&&!vis[v])
GaoCnt(v);
}
} int main()
{
int n,m;
scanf("%d%d",&n,&m);
int s=,t=n+;// 源点,汇点
LL ans=;
for(int i=;i<=n;i++)
{
LL c;
scanf("%lld",&c);
if(c>)
{
ans+=c; //正权值求和
add_edge(s,i,c);
}
else if(c<)
{
add_edge(i,t,-c);
}
}
for (int i = ; i < m; ++i) {
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v,INF);
}
ans-= Dinic(s,t);
GaoCnt(s);
printf("%d %lld\n",cnt-,ans);
return ;
}

参考自:hankcsyogykwan

POJ 2987 Firing【最大权闭合图-最小割】的更多相关文章

  1. poj 2987 Firing 最大权闭合图

    题目链接:http://poj.org/problem?id=2987 You’ve finally got mad at “the world’s most stupid” employees of ...

  2. [luoguP2762] 太空飞行计划问题(最大权闭合图—最小割—最大流)

    传送门 如果将每一个实验和其所对的仪器连一条有向边,那么原图就是一个dag图(有向无环) 每一个点都有一个点权,实验为收益(正数),仪器为花费(负数). 那么接下来可以引出闭合图的概念了. 闭合图是原 ...

  3. POJ 2987 - Firing - [最大权闭合子图]

    题目链接:http://poj.org/problem?id=2987 Time Limit: 5000MS Memory Limit: 131072K Description You’ve fina ...

  4. POJ 2987 Firing | 最大权闭合团

    一个点带权的图,有一些指向关系,删掉一个点他指向的点也不能留下,问子图最大权值 题解: 这是最大权闭合团问题 闭合团:集合内所有点出边指向的点都在集合内 构图方法 1.S到权值为正的点,容量为权值 2 ...

  5. B1391 [Ceoi2008]order 最大权闭合图 最小割

    啊啊啊,假的题吧!!!我用的当前弧优化T了6个点,其他人不用优化AC!!!震惊!!!当前弧优化是假的吧!!! 到现在我也没调出来...大家帮我看看为啥70.... 来讲一下这个题的思路,就是设一个源点 ...

  6. POJ2987 Firing 最大权闭合图

    详情请参考http://www.cnblogs.com/kane0526/archive/2013/04/05/3001557.html 值得注意的地方,割边会把图分成两部分,一部分和起点相连,另一部 ...

  7. 洛谷 P4174 [NOI2006]最大获利 && 洛谷 P2762 太空飞行计划问题 (最大权闭合子图 && 最小割输出任意一组方案)

    https://www.luogu.org/problemnew/show/P4174 最大权闭合子图的模板 每个通讯站建一个点,点权为-Pi:每个用户建一个点,点权为Ci,分别向Ai和Bi对应的点连 ...

  8. BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)

    题意 自己看吧 BZOJ传送门 分析 - 这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少. 建一个图,如果选uuu必须选vvv,则uuu向vvv连边 ...

  9. 【最大权闭合子图 最小割】bzoj1497: [NOI2006]最大获利

    最大权闭合子图的模型:今天才发现dinic板子是一直挂的…… Description 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS&T通讯公司在 ...

随机推荐

  1. requests库入门12-文件上传和下载

    因为找不到可以演示上传接口,所以只能纯代码了 文件上传 上传文件是在请求中使用files参数,files需要指向一个dict,然后dict里面的键是接口中对应文件名的字段,而值就是打开这个文件读取到内 ...

  2. 效率较高的php下读取文本文件的代码

    主要用下面这两个方法fread和 fgets的区别大家需要注意下     fread :以字节位计算长度,按照指定的长度和次数读取数据,遇到结尾或完成指定长度读取后停止.  fgets :整行读取,遇 ...

  3. csrfguard3.1 部署笔记

    1:git clone 导入csrfguard 2:点击菜单栏View->Tool  Windows->Maven projects 3:Lifecycle clean build 4:t ...

  4. h5 右下角浮动按钮, 纯css实现

    2017年11月22日19:00:22 效果:                  代码: /** 右下角跳转按钮 跳转到列表 */ #list_note_icon { position: fixed; ...

  5. char、nchar、varchar、nvarchar 的区别

    char.varchar.nchar.nvarchar为数据库中常用的字符类型,使用上要综合考虑空间利用率与存取速度.它们的区别如下: 实例解析: 定义char[9].varchar[9].nchar ...

  6. checkstyle.xml Code Style for Eclipse

    1. Code Templates [下载 Code Templates] 打开 Eclipse -> Window -> Preferences -> Java -> Cod ...

  7. js去除空格12种方法

    注:本文非本人原著:原文作者: 黄卉  <js去除空格12种方法> //JS去除空格的方法目前共有12种: //实现1 String.prototype.trim = function() ...

  8. Confluence 6 修改日志文件的大小数量和级别

    修改日志文件的大小和数量 在默认的情况下,Confluence 将会保持 5 个日志文件,每一个日志文件的大小超过 20 MB 的时候将会被重写. 你可以修改默认日志文件的大小和数量,通过编辑 < ...

  9. Confluence 6 当前使用的数据库状态

    进入  > 基本配置(General Configuration) > 问题检查和支持工具(Troubleshooting and support tools) 你就可以看到当前使用的数据 ...

  10. Java 本周四、五的相关研究——Excel 的文件管理(数据库初步)

    日期:2018.9.28 星期五 博客期:013 说到这里,就二话不多说了!这次研习的是与Excel表相关联的方法 1.导入jar包(需要自己下载) 2.AccountManager类的实现(关键看非 ...