题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4309

思路:2^12枚举修复哪些桥,不修复的桥没有花费,连接的边流量为1,要修复的桥则计算花费,边的流量为无穷,建立最大流模型来求解,增加一个源点S(0),和一个汇点T(n+1)。S向每个有人的点,连一条容量为人数的边,图中普通的u->v的有向边,连一条u->v的流量为无穷的边,对于u->v的隧道,可以连接u->v的流量无穷的边,和u->T的流量为隧道人数上限的边,求解最大流即可;

ps:枚举状态用递归即可。

View Code

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 using namespace std;
  5 #define MAXN 222
  6 #define MAXM 3333
  7 #define inf 1<<30
  8
  9 struct Edge{
 10     int v,cap,next;
 11 }edge[MAXM],E[MAXM];
 12
 13 struct ReEdge{
 14     int index,cap;
 15 }reedge[MAXM];
 16
 17 int head[MAXN];
 18 int cur[MAXN];
 19 int pre[MAXN];
 20 int level[MAXN];
 21 int gap[MAXN];
 22 int NV,NE,vs,vt,n,m,total,mincost,maxnum;
 23
 24 void Insert(int u,int v,int cap,int cc=0){
 25     edge[NE].v=v;edge[NE].cap=cap;
 26     edge[NE].next=head[u];head[u]=NE++;
 27
 28     edge[NE].v=u;edge[NE].cap=cc;
 29     edge[NE].next=head[v];head[v]=NE++;
 30 }
 31
 32
 33 int SAP(int vs,int vt){
 34     memset(pre,-1,sizeof(pre));
 35     memset(level,0,sizeof(level));
 36     memset(gap,0,sizeof(gap));
 37     for(int i=0;i<=n+1;i++)cur[i]=head[i];
 38     int u=pre[vs]=vs,maxflow=0,aug=-1;
 39     gap[0]=NV;
 40     while(level[vs]<NV){
 41 loop:
 42         for(int &i=cur[u];i!=-1;i=edge[i].next){
 43             int v=edge[i].v;
 44             if(edge[i].cap&&level[u]==level[v]+1){
 45                 aug==-1?aug=edge[i].cap:aug=min(aug,edge[i].cap);
 46                 pre[v]=u;
 47                 u=v;
 48                 if(v==vt){
 49                     maxflow+=aug;
 50                     for(u=pre[u];v!=vs;v=u,u=pre[u]){
 51                         edge[cur[u]].cap-=aug;
 52                         edge[cur[u]^1].cap+=aug;
 53                     }
 54                     aug=-1;
 55                 }
 56                 goto loop;
 57             }
 58         }
 59         int minlevel=NV;
 60         for(int i=head[u];i!=-1;i=edge[i].next){
 61             int v=edge[i].v;
 62             if(edge[i].cap&&minlevel>level[v]){
 63                 cur[u]=i;
 64                 minlevel=level[v];
 65             }
 66         }
 67         gap[level[u]]--;
 68         if(gap[level[u]]==0)break;
 69         level[u]=minlevel+1;
 70         gap[level[u]]++;
 71         u=pre[u];
 72     }
 73     return maxflow;
 74 }
 75
 76
 77 void Solve(int num,int cost){
 78     if(num>=total){
 79         for(int i=0;i<NE;i+=2){
 80             edge[i].cap+=edge[i^1].cap;
 81             edge[i^1].cap=0;
 82         }
 83         int ans=SAP(vs,vt);
 84         if(ans>maxnum){maxnum=ans;mincost=cost;}
 85         else if(ans==maxnum&&mincost>cost){    mincost=cost;}
 86     }else {
 87         Solve(num+1,cost);
 88         edge[reedge[num].index].cap=inf;
 89         Solve(num+1,cost+reedge[num].cap);
 90         edge[reedge[num].index].cap=1;
 91         edge[reedge[num].index^1].cap=0;
 92     }
 93 }
 94
 95 int main(){
 96     int city_num,u,v,w,p;
 97     while(~scanf("%d%d",&n,&m)){
 98         vs=0,vt=n+1,NV=n+2,NE=0,total=0,mincost=inf,maxnum=0;
 99         memset(head,-1,sizeof(head));
100         for(int i=1;i<=n;i++){
101             scanf("%d",&city_num);
102             Insert(vs,i,city_num);
103         }
104         for(int i=1;i<=m;i++){
105             scanf("%d%d%d%d",&u,&v,&w,&p);
106             if(p==0)Insert(u,v,inf);
107             else if(p<0){Insert(u,vt,w);Insert(u,v,inf);}
108             else {
109                 reedge[total].index=NE;
110                 reedge[total++].cap=w;
111                 Insert(u,v,1);
112             }
113         }
114         Solve(0,0);
115         if(!maxnum)puts("Poor Heaven Empire");
116         else printf("%d %d\n",maxnum,mincost);
117     }
118     return 0;
119 }

hdu 4309(最大流+枚举状态)相关推荐

  1. hdu 4309 最大流 + DFS

    题意:      给以三种有向边     (1) 隧道,可以过无数人,也可以藏c个人.     (2) 路,只能过人(流量INF).     (3)古桥,如果不修理可以过1个人,修理可以过无数个人,但 ...

  2. C++ Primer 5th笔记(8)chapter8 类:IO库-流的状态

    1. 定义:流有状态,表示是否出错. eg. 通常在使用它时要测试它的状态: while (cin >> word) 注:只有在非错误状态下,stream才能被读写 2. 流的状态值 st ...

  3. LeetCode 2002. 两个回文子序列长度的最大乘积(状态压缩+枚举状态子集+预处理)

    文章目录 1. 题目 2. 解题 2.1 超时 2.2 预处理优化 1. 题目 给你一个字符串 s ,请你找到 s 中两个 不相交回文子序列 ,使得它们长度的 乘积最大 . 两个子序列在原字符串中如果 ...

  4. HDU 5025Saving Tang Monk BFS + 二进制枚举状态

    3A的题目,第一次TLE,是因为一次BFS起点到终点状态太多爆掉了时间. 第二次WA,是因为没有枚举蛇的状态. 解体思路: 因为蛇的数目是小于5只的,那就首先枚举是否杀死每只蛇即可. 然后多次BFS, ...

  5. 【网络流】 HDU 4309 Seikimatsu Occult Tonneru 状压枚举边

    题意:有三种类型的路 类型 1. 从 U 到 V  能走INF个人 能躲 d 个人 类型 2. 从 U 到 V 能走INF 个人 不能 躲人 类型 3. 从 U 到 V 能走INF 个人 要用该路时需 ...

  6. HDU 4628 Pieces(DP + 状态压缩)

    Pieces 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4628 题目大意:给定一个字符串s,如果子序列中有回文,可以一步删除掉它,求把整个序列删除 ...

  7. HDU 1074 Doing Homework【状态压缩DP】

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题意: 给定作业截止时间和完成作业所需时间,比截止时间晚一天扣一分,问如何安排作业的顺序使得最 ...

  8. hdu 4888 最大流慢板

    http://acm.hdu.edu.cn/showproblem.php?pid=4888 添加一个源点与汇点,建图如下: 1. 源点 -> 每一行对应的点,流量限制为该行的和 2. 每一行对 ...

  9. hdu4901 枚举状态(找集合对S(xor) ==T(and))

    题意:      给你一个串数字,然后让你在这里面挑取两个集合S ,T,集合的要求是 (1)不能为空 (2)S集合的所有元素必须在T集合的左边 (3)S集合的XOR == T集合的AND      问 ...

最新文章

  1. 12 种方式轻松实现 Ruby 调用
  2. 云优后台提交显示parsererror_【Shopee新手开店】卖家后台管理及设置
  3. 晶振噪声及杂散_如何判断是否需要使用分立式晶振和振荡器呢?
  4. Mysq表的创建和l数据类型
  5. OpenGL 行星asteroids系统的实例
  6. matlab正弦光栅,科学网—光栅-正弦,矩形 - 宗兆玉的博文
  7. 元空间和直接内存_JVM探秘:Java内存区域
  8. WPF DataGrid
  9. 【Animation】 使用handler和Runnable实现某一个控件的抖动效果
  10. VC 2012 中调用WebBrowser简单的实现过程(图解过程)
  11. Redis分布式锁之:RedLock
  12. Java 计算两点坐标距离
  13. 第2章-系统控制原理 -> 李雅普诺夫稳定性分析
  14. java读取xml转json
  15. 优化百度ueditor编辑器,增加秀米插件、手机端预览等功能,与egg-ueditor完美结合
  16. 计算机一级用写在简历里面吗,写简历要小心,简历填写最忌讳的是什么,你知道吗?...
  17. oracle 12c创建归档,oracle 12c 数据归档 即Using In-Database Archiving feature
  18. vb UBound 数据上界
  19. Android中的动画(二)和ButterKnife (黄油刀)
  20. python显示gif图片_Python给gif图片加文字水印

热门文章

  1. Java Web - Struts2基本执行流程
  2. 学习笔记95—不要错过的科研神器
  3. AES CBC模式下的CBC bit flipping Attack
  4. Canvas知识点汇总
  5. 201671010144 2016-2017-2 《java程序设计》--认识java!
  6. 通过修改Tomcat配置,解决乱码问题
  7. glut64位操作系统安装
  8. jQuery 人脸识别插件,支持图片和视频
  9. 博客园7月底至8月初51Aspx源码发布详情
  10. ios请求头解决参数中文乱码_解决请求参数的中文乱码问题(get、post)