题目


求选最少点个数的最大权闭合子图。(板子题)


最小割入门题,什么都不想说,丢个别人题解地址就跑。

附加几点个人理解:与s相通的S点集是闭合子图,剩下的与t相通的T点集是其他的。任意一个割都保证了有一个闭合子图是S集。

然后是选最少点个数,考虑加入最大权时存在多个方案,选的点个数不同,既然各方案都是闭合的,那我全选也是闭合的,就会创出更多权值,与之前最大权矛盾,所以最大权一定点数唯一,选法唯一。那就直接从s点找残量网络,把他的点集都找一下,计下数即可。←这里有个原理,做最小割(最大流),而最大流算好后因为最小割必然满流,所以最小割对应的边残量为0,则dfs时就不遍历残量为0的边。←刚才又提到一个结论,一定存在一个最大流使得最小割在其中满流,这里口胡证明一下,防止以后我忘了:最大流做完后s所能到的所有点S集,以及另一T集之间,应当是有一些边满流的也就是残量为0的,不然就可继续增广,就不是最大流了,那这些边对应了一个割CUT[S,T],再由任意流小于等于任意割结论(打个比方,水流将流到割断的地方,而水流量小于等于容量,故得证)知,任意一个割大于等于这个最大流,即大于等于这个割,那这个割就是最小割,而她满流。证毕。

UPD:我现在看发现当时好像证的有点问题。。所以请不要信以为真,有空回来补详细的一些证明,当时只是个网络流初心者。

我还是太菜了啊。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<queue>
  5. using namespace std;
  6. typedef long long ll;
  7. typedef pair<int,int> pii;
  8. template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
  9. template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
  10. template<typename T>inline T _min(T A,T B){return A<B?A:B;}
  11. template<typename T>inline T _max(T A,T B){return A>B?A:B;}
  12. template<typename T>inline void inc(T&A,T B){A+=B;}
  13. template<typename T>inline T read(T&x){
  14. x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
  15. while(isdigit(c))x=x*10+c-'0',c=getchar();return f?x=-x:x;
  16. }
  17. const int N=+,M=+;ll INF=1ll<<;
  18. int Head[N],cur[N],Next[M<<],v[M<<],dis[N],vis[N],tot=,n,cnt,m,s,t;ll w[M<<];
  19.  
  20. inline void Addedge(int x,int y,ll z){
  21. v[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=z;
  22. v[++tot]=x,Next[tot]=Head[y],Head[y]=tot,w[tot]=;
  23. }
  24. #define y v[j]
  25. inline int bfs(){
  26. queue<int> q;memset(dis,,sizeof dis),dis[s]=,q.push(s);
  27. for(register int i=;i<=n+;++i)cur[i]=Head[i];
  28. while(!q.empty()){
  29. int x=q.front();q.pop();
  30. for(register int j=Head[x];j;j=Next[j])if(w[j]&&!dis[y]){
  31. dis[y]=dis[x]+,q.push(y);
  32. if(y==t)return ;
  33. }
  34. }
  35. return ;
  36. }
  37. ll dinic(int x,ll flow){
  38. if(!flow||x==t)return flow;
  39. ll rest=flow,k;
  40. for(register int j=cur[x];j&&rest;cur[x]=j,j=Next[j])if(w[j]&&dis[y]==dis[x]+){
  41. if(!(k=dinic(y,_min(rest,w[j]))))dis[y]=;
  42. rest-=k,w[j]-=k,w[j^]+=k;
  43. }
  44. return flow-rest;
  45. }
  46. void dfs(int x){
  47. for(register int j=Head[x];j;j=Next[j])if(w[j]&&!vis[y])vis[y]=,++cnt,dfs(y);
  48. }
  49. #undef y
  50. int x,y;
  51. ll maxflow,ans,z;
  52.  
  53. int main(){//freopen("tmp.in","r",stdin);freopen("tmp.out","w",stdout);
  54. read(n),read(m);s=n+,t=s+;
  55. for(register int i=;i<=n;++i)read(z)>?(inc(ans,z),Addedge(s,i,z)):Addedge(i,t,-z);
  56. for(register int i=;i<=m;++i)read(x),read(y),Addedge(x,y,INF);
  57. while(bfs())inc(maxflow,dinic(s,INF));
  58. ans-=maxflow;cnt=,vis[s]=,dfs(s);
  59. printf("%d %lld\n",--cnt,ans);
  60. return ;
  61. }

Upd:今天被巨佬嘲讽了说我快读用位运算太慢。orzorzorzTQL

poj2987 Firing[最小割]的更多相关文章

  1. 【POJ 2987】Firing (最小割-最大权闭合子图)

    裁员 [问题描述] 在一个公司里,老板发现,手下的员工很多都不务正业,真正干事员工的没几个,于是老板决定大裁员,每开除一个人,同时要将其下属一并开除,如果该下属还有下属,照斩不误.给出每个人的贡献值和 ...

  2. POJ 2987 Firing【最大权闭合图-最小割】

    题意:给出一个有向图,选择一个点,则要选择它的可以到达的所有节点.选择每个点有各自的利益或损失.求最大化的利益,以及此时选择人数的最小值. 算法:构造源点s汇点t,从s到每个正数点建边,容量为利益.每 ...

  3. POJ2987 Firing 【最大权闭合图】

    POJ2987 Firing Description You've finally got mad at "the world's most stupid" employees o ...

  4. poj2987 Firing 最大权闭合子图 边权有正有负

    /** 题目:poj2987 Firing 最大权闭合子图 边权有正有负 链接:http://poj.org/problem?id=2987 题意:由于金融危机,公司要裁员,如果裁了员工x,那么x的下 ...

  5. POJ 3308 Paratroopers(最小割EK(邻接表&矩阵))

    Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the ...

  6. BZOJ 1391: [Ceoi2008]order [最小割]

    1391: [Ceoi2008]order Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1509  Solved: 460[Submit][Statu ...

  7. BZOJ-2127-happiness(最小割)

    2127: happiness(题解) Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1806  Solved: 875 Description 高一 ...

  8. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  9. BZOJ3438 小M的作物(最小割)

    题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=3438 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为 ...

随机推荐

  1. cef加载flash的办法

    cef有2种加载flash插件的方式, 1,npapi,这种方式是调用系统自带的flash插件,由于有安全性方面的问题,已经被新版cef禁用. 2,ppapi,也就是 pepper flash,这是谷 ...

  2. B/S结构-登录页面-测试用例设计

    页面描述: 有一个登陆页面, 假如上面有2个textbox, 一个提交按钮 测试需求: 请针对这个页面设计30个以上的testcase 功能测试(Function test) 0. 什么都不输入,点击 ...

  3. python-Web-django-自定义标签

    简化:@register.simple_tag def current_time(token): return datetime.datetime.now().strftime(str(token)) ...

  4. 【HANA系列】【第六篇】SAP HANA XS使用JavaScript(JS)调用存储过程(Procedures)

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列][第六篇]SAP HANA XS ...

  5. mac sudo异常

    dsenableroot -d -u <your_admin_username> -p <your_password>  

  6. Java学习-4

    面向对象的三大特征之一:继承性 主要解决问题:共性抽取 继承关系当中的特点:子类可以拥有父类的“内容”,子类还可以拥有自己专属的内容 定义一个父类的格式(就是定义一个普通类的格式): Public c ...

  7. 天勤考研数据结构笔记—栈的C语言实现

    栈的基本概念 栈的定义:栈是一种只能在一端进行插入或删除操作的线性表.其中允许进行插入或删除的一端称为栈顶(top).栈顶是由一个称为栈顶指针的位置指示器(其实就是一个变量,对于顺序栈,就是数组索引, ...

  8. java-selenium浏览器常用操作命令

    一.浏览器操作命令 启动火狐浏览器(49版本以下) System.setProperty("webdriver.firefox.bin","D:\\Firefox\\fi ...

  9. Mybatis动态SQL之使用foreach完成复杂查询

    一.foreach概述 对于一些SQL语句中含有in条件.需要迭代条件集合来生产的情况,就需要使用foreach标签来实现SQL条件的迭代.foreach主要用在构建in条件中,它可以在SQL语句中迭 ...

  10. spark教程(10)-sparkSQL

    sparkSQL 的由来 我们知道最初的计算框架叫 mapreduce,他的缺点是计算速度慢,还有一个就是代码比较麻烦,所以有了 hive: hive 是把类 sql 的语句转换成 mapreduce ...