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. flask用宏渲染表单模板时,表单提交后,如果form.validate_on_submit()返回的是false的可能原因

    flask用宏渲染表单模板时,表单提交后,提交的内容符合DataRequired()校验, 但是form.validate_on_submit()返回的是False, 原因可能是表单模板中的<f ...

  2. 2017-2018-2 20165316 实验三《敏捷开发与XP实践》实验报告

    2017-2018-2 20165316 实验三<敏捷开发与XP实践>实验报告 实验目的 安装 alibaba 插件,解决代码中的规范问题.再研究一下Code菜单,找出一项让自己感觉最好用 ...

  3. centos 6.8操作系统安装arcgis server 10.4

    1.检查操作系统中软件包的安装,第一条和第二条是图形界面工具,可以不装. 可以用rpm -qa | grep 软件名   命令检查软件包是否已经安装 主机名不能包含下划线,可以用hostname检查主 ...

  4. 51nod 1130 N的阶乘的长度 V2(斯特林近似)

    输入N求N的阶乘的10进制表示的长度.例如6! = 720,长度为3.   Input 第1行:一个数T,表示后面用作输入测试的数的数量.(1 <= T <= 1000) 第2 - T + ...

  5. 一起学习在 Ubuntu 上授予和移除 sudo 权限

    如你所知,用户可以在 Ubuntu 系统上使用 sudo 权限执行任何管理任务.在 Linux 机器上创建新用户时,他们无法执行任何管理任务,直到你将其加入 sudo 组的成员.在这个简短的教程中,我 ...

  6. 关于java 操作linux命令的 一些相关

    ThreadPoolExecutor pool= new ThreadPoolExecutor(5,10, 3, TimeUnit.SECONDS, new LinkedBlockingQueue&l ...

  7. 写出优质Java代码的4个技巧

    我们平时的编程任务不外乎就是将相同的技术套件应用到不同的项目中去,对于大多数情况来说,这些技术都是可以满足目标的.然而,有的项目可能需要用到一些特别的技术,因此工程师们得深入研究,去寻找那些最简单但最 ...

  8. javaweb笔记—01(编程英语、常识、Tomcat配置问题)

    第一部分: 编程英语: legal:adj. 法律的:合法的:法定的 Userful :出版商  sponsor: n. 赞助者:主办者:保证人 | vt. 赞助:发起 essential:n. 本质 ...

  9. Leetcode480-Sliding Window Median

    Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...

  10. FileReader 获取图片base64数据流 并 生成图片

    <?php if(isset($_GET['upload']) && $_GET['upload'] == 'img'){ if(isset($_GET['stream_type ...