http://acm.hdu.edu.cn/showproblem.php?pid=4309

题意:

有n个城市,每个城市有num[i]个居民,有敌人要进行地毯式轰击,居民们要逃到隧道去。现在有隧道,隧道允许无限个人通过,并且可以容纳w个人;有桥,可以允许无限个人通过,但是不能容纳人;还有一些破桥,修复这些破桥需要w花费,如果不修复,那么最多只能通过一人,如果修复了,那么可以通过无限个人。求出在能安全到达隧道的最大人数时的最小代价。(上述都是单向边)

思路:
出题人也是有心了。。在题目中有说破桥的名字是用十二星座命名的,也就是说,破桥最多只有12座,既然这样,完全就可以二进制枚举了。

建立超级源点,源点向每个城市连边,容量为城市人数;隧道连u->v的容量为inf的边,并且连u->T的容量为w的边,桥连u->v的容量为inf的边。破桥就是二进制枚举修复的情况。多次求最大流即可。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef long long ull;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn = + ; int num[maxn]; struct node
{
int u,v,w,p;
node(int u, int v, int w, int p):u(u),v(v),w(w),p(p){}
}; vector<node> vec[]; struct Edge
{
int from,to,cap,flow;
Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
}; struct Dinic
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int cur[maxn];
int d[maxn]; void init(int n)
{
this->n=n;
for(int i=;i<n;++i) G[i].clear();
edges.clear();
} void AddEdge(int from,int to,int cap)
{
edges.push_back( Edge(from,to,cap,) );
edges.push_back( Edge(to,from,,) );
m=edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BFS()
{
queue<int> Q;
memset(vis,,sizeof(vis));
vis[s]=true;
d[s]=;
Q.push(s);
while(!Q.empty())
{
int x=Q.front(); Q.pop();
for(int i=;i<G[x].size();++i)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to] && e.cap>e.flow)
{
vis[e.to]=true;
d[e.to]=d[x]+;
Q.push(e.to);
}
}
}
return vis[t];
} int DFS(int x,int a)
{
if(x==t || a==) return a;
int flow=, f;
for(int &i=cur[x];i<G[x].size();++i)
{
Edge &e=edges[G[x][i]];
if(d[e.to]==d[x]+ && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>)
{
e.flow +=f;
edges[G[x][i]^].flow -=f;
flow +=f;
a -=f;
if(a==) break;
}
}
return flow;
} int Maxflow(int s,int t)
{
this->s=s; this->t=t;
int flow=;
while(BFS())
{
memset(cur,,sizeof(cur));
flow +=DFS(s,INF);
}
return flow;
}
}DC; int n,m; int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
vec[].clear(); vec[].clear(); vec[].clear();
for(int i=;i<=n;i++) scanf("%d",&num[i]);
for(int i=;i<=m;i++)
{
int u,v,w,p;
scanf("%d%d%d%d",&u,&v,&w,&p);
if(p<) vec[].push_back(node(u,v,w,p));
else if(p==) vec[].push_back(node(u,v,w,p));
else vec[].push_back(node(u,v,w,p));
}
int people = -, cost = INF;
int tunnel = vec[].size();
if(tunnel == ) {puts("Poor Heaven Empire");continue;}
int bridge = vec[].size();
int src = , dst = n+;
for(int state=;state<(<<bridge);state++)
{
int tmp = ;
DC.init(dst+);
for(int i=;i<=n;i++) DC.AddEdge(src,i,num[i]);
for(int i=;i<vec[].size();i++)
{
node p = vec[][i];
DC.AddEdge(p.u,p.v,INF);
DC.AddEdge(p.u,dst,p.w);
}
for(int i=;i<vec[].size();i++)
{
node p = vec[][i];
DC.AddEdge(p.u, p.v, INF);
}
for(int i=;i<vec[].size();i++)
{
node p = vec[][i];
if((<<i)&state)
{
tmp += p.w;
DC.AddEdge(p.u, p.v, INF);
}
else
{
DC.AddEdge(p.u, p.v, );
}
}
int flow = DC.Maxflow(src,dst);
if(flow == people) cost = min(cost,tmp);
if(flow > people)
{
people = flow;
cost = tmp;
}
}
if(people == -) puts("Poor Heaven Empire");
else printf("%d %d\n",people,cost);
}
return ;
}

HDU 4309 Seikimatsu Occult Tonneru(最大流+二进制枚举)的更多相关文章

  1. HDU 4309 Seikimatsu Occult Tonneru

    Seikimatsu Occult Tonneru Time Limit: 6000ms Memory Limit: 32768KB This problem will be judged on HD ...

  2. HDU 4309 Seikimatsu Occult Tonneru 网络流量+像缩进

    主题链接:点击打开链接 意甲冠军: 题意:给出一张N(N<=100)个点,M(M<=1000条)边的有向图. 每一个点上都有一些人.每条边有4个属性(u,v,w,p). 这些边分为三种:( ...

  3. HDU 4309 Seikimatsu Occult Tonneru (状压 + 网络流)

    题意:输入 n 个城市 m 条边,但是边有三种有向边 a b  c d,第一种是 d 是 0,那么就是一条普通的路,可以通过无穷多人,如果 d < 0,那么就是隧道,这个隧道是可以藏 c 个人, ...

  4. HDU4309-Seikimatsu Occult Tonneru(最大流)

    Seikimatsu Occult Tonneru Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  5. Seikimatsu Occult Tonneru(网络流,状态数(建不建边)不多时,可考虑直接进行枚举

    http://acm.hdu.edu.cn/showproblem.php?pid=4309 总结:边可存东西时,可新建一个点x连接u.v,x再连向汇点: #include<iostream&g ...

  6. HDU 3549 Flow Problem(最大流)

    HDU 3549 Flow Problem(最大流) Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/ ...

  7. hdu 3118(二进制枚举)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3118 思路:题目要求是去掉最少的边使得图中不存在路径长度为奇数的环,这个问题等价于在图中去掉若干条边, ...

  8. HDU.1796 How many integers can you find ( 组合数学 容斥原理 二进制枚举)

    HDU.1796 How many integers can you find ( 组合数学 容斥原理 二进制枚举) 题意分析 求在[1,n-1]中,m个整数的倍数共有多少个 与 UVA.10325 ...

  9. hdu 6214 Smallest Minimum Cut[最大流]

    hdu 6214 Smallest Minimum Cut[最大流] 题意:求最小割中最少的边数. 题解:对边权乘个比边大点的数比如300,再加1 ,最后,最大流对300取余就是边数啦.. #incl ...

随机推荐

  1. 【转载】selenium与自动化测试成神之路

    Python selenium —— selenium与自动化测试成神之路 置顶 2016年09月17日 00:33:04 阅读数:43886 Python selenium —— selenium与 ...

  2. python迭代器以及生成器

    迭代器iter():节省内存 Iter()迭代器 每一次输出下一个值 >>> a=iter(range(10)) >>> a.next() 0 >>&g ...

  3. Linux基础命令---pgrep

    pgrep pgrep指令可以按名字或者其他属性搜索指定的进程,显示出进程的id到标准输出. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedo ...

  4. centos安装angr

    1.angr环境 yum install -y python-dev libffi-dev build-essential virtualenvwrapper mkvirtualenv angr 问题 ...

  5. JustOj 2042: Dada的游戏

    题目描述 Dada无聊时,喜欢做一个游戏,将很多钱分成若干堆排成一列,每堆钱数不固定,谁能找出每堆钱数严格递增的最长区间,谁就是人生赢家了.Dada可能脑子里的水还没干,她找不出来,你来帮她找找吧. ...

  6. 大数据学习路线:Zookeeper集群管理与选举

    大数据技术的学习,逐渐成为很多程序员的必修课,因为趋势也是因为自己的职业生涯.在各个技术社区分享交流成为很多人学习的方式,今天很荣幸给我们分享一些大数据基础知识,大家可以一起学习! 1.集群机器监控 ...

  7. java加载配置文件信息

    #基金数据存放根目录fund_save_root_path=E:/fundCrawling #龙虎榜数据存放根目录long_hu_root_path=E:/longHuCrawling #巨潮数据存放 ...

  8. The Little Prince-12/12

    The Little Prince-12/12 双十二,大家有没有买买买呢?宝宝双十一之后就吃土了,到现在,叶子都长出来了!!! 当你真的喜欢一个人的时候 就会想很多 会很容易办蠢事 说傻话 小王子要 ...

  9. Python进阶【第七篇】文件处理

    一.文件操作 在Python中,文件读写是最常见的操作.对文件的操作为: #1. 打开文件,得到文件句柄并赋值给一个变量 f=open('a.txt','r',encoding='utf-8') #默 ...

  10. Python进阶【第六篇】内置函数中好玩的几个(今天写的太水)

    zip()函数 两个参数一一对应,参数是序列类型,序列包括列表,元组,字符串,当两个序列不等长时,按公共最长部分匹配,形似“拉链”. max()和min()函数 以max()为例,min()类似,只是 ...