【HDU】 4309 Seikimatsu Occult Tonneru
2016-05-14 10:47
411 查看
Seikimatsu Occult Tonneru
题目链接
Seikimatsu Occult Tonneru题目大意
说现在有n个城市,每个城市都住着PiP_i人,城市之间可能会有边连接,而边有3种,一种是Tunnels,可以躲m人,同时可以通过任意数
量的人。第二种是Road,只能通过人,但是并不能躲。第三种是
Bridge,不修的话只能通过1人,修的话可以通过任意数量的人(就跟
第二种边一样了)。
题解
这一题主要是建图,首先从源点向每一个有人的城市建立一条人数为PiP_i的边,对于第一种边,从弧尾节点(u)向汇点建立一条长度为该
边可通过人数的边,再从u到v建立一条长度为INF的边。对于第二种
边,建立一条长度为INF的边。对于第三种边,因为这东西实在是没有
什么好方法去处理,而且最多只有12条Bridge,看到题目6秒的限制,
想到直接暴力 时间复杂度
O(2numbridge(numbridge+Sap))O(2^{numbridge}(numbridge+Sap) )
numbirdgenumbirdge代表桥的个数,SapSap是求最大流的复杂度,我这里用的
SapSap所以用SapSap表示了。
代码
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #define INF 0x3fffffff using namespace std; struct edge { int u,v,w,d,next; }; edge e[2500],re[2500]; int n,m,p[110],nume,u,v,w,x,h,high,bri[15]; int flow[110],dis[110],pre[110],gap[110],path[110],cost,cur[110]; void addedge(int u,int v,int w,int d) { e[nume].u=u; e[nume].v=v; e[nume].d=d; e[nume].w=w; e[nume].next=pre[u]; pre[u]=nume; nume++; } void bfs(int st,int des) { int q[110],h=0,t=0; memset(q,0,sizeof(q)); memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); q[h++]=st; dis[st]=1; gap[1]=1; while (h!=t) { int u=q[t++]; for (int i=pre[u];i!=-1;i=e[i].next) { int v=e[i].v; if (!dis[v]) { dis[v]=dis[u]+1; gap[dis[v]]++; q[h++]=v; } } } } int sap(int st,int des) { memset(flow,0,sizeof(flow)); memset(path,0,sizeof(path)); memcpy(cur,pre,sizeof(cur)); flow[st]=INF; bfs(des,st); int u=st,k,ans=0; while (dis[st]<=n+2) { if (u==des) { k=des; while (k!=st) { e[path[k]].d-=flow[des]; e[path[k]^1].d+=flow[des]; k=e[path[k]].u; } ans+=flow[des]; u=st; } bool flag=1; for (int i=cur[u];i!=-1;i=e[i].next) { int v=e[i].v; if (dis[u]==dis[v]+1 && e[i].d) { path[v]=i; cur[u]=i; flow[v]=min(e[i].d,flow[u]); u=v; flag=0; break; } } if (flag) { int v,mindis=INF-1; cur[u]=pre[u]; if (--gap[dis[u]]==0) return ans; for (int i=cur[u];i!=-1;i=e[i].next) { v=e[i].v; if (e[i].d && dis[v]<mindis) { mindis=dis[v]; cur[u]=i; } } dis[u]=mindis+1; if (dis[u]!=INF) gap[dis[u]]++; if (u!=st) u=e[path[u]].u; } } return ans; } int main() { while (scanf("%d%d",&n,&m)!=EOF) { memset(e,0,sizeof(e)); memset(p,0,sizeof(p)); memset(re,0,sizeof(re)); memset(pre,-1,sizeof(pre)); memset(bri,0,sizeof(bri)); h=0; int sum1=0; nume=0; for (int i=1;i<=n;i++) { scanf("%d",&p[i]); sum1+=p[i]; if (p[i]) { addedge(0,i,0,p[i]); addedge(i,0,0,0); } } if (!sum1) { printf("Poor Heaven Empire\n"); continue; } for (int i=0;i<m;i++) { scanf("%d%d%d%d",&u,&v,&w,&x); if (x<0) { addedge(u,v,0,INF); addedge(v,u,0,0); addedge(u,n+1,0,w); addedge(n+1,u,0,0); } else if (x==0) { addedge(u,v,0,INF); addedge(v,u,0,0); } else { bri[h++]=nume; addedge(u,v,w,1); addedge(v,u,0,0); } } memcpy(re,e,sizeof(re)); int ansflow=0,anscost=INF; for (int i=0;i<(1<<h);i++) { memcpy(e,re,sizeof(e)); cost=0; for (int j=0;j<h;j++) if ((1<<j)&i) { e[bri[j]].d=INF; cost+=e[bri[j]].w; } else e[bri[j]].d=1; //map-finish int x=sap(0,n+1); if (ansflow<x) { ansflow=x; anscost=cost; } else if (ansflow==x) anscost=min(anscost,cost); } if (ansflow==0) printf("Poor Heaven Empire\n"); else printf("%d %d\n",ansflow,anscost); } return 0; }
相关文章推荐
- sdibt 1244 烦人的幻灯片
- php 可变变量
- magento 列表页显示产品属性值的几种调用方式
- 【bzoj1149】 [CTSC2007]风玲Mobiles
- openjudge7624 山区建小学
- hdoj-2099-整除的尾数
- 判断无向图是否有环
- Docker学习 ----常用操作命令大全及例子[陆续更新中...]
- word2vec (一) 简介与训练过程概要
- 如何制作纯 ASCII 文本流程图
- Python安装模块出错(ImportError: No module named setuptools)解决方法
- Android小技巧
- 街区最短路径问题
- oracle数据库的静默(Quiesce)状态
- C++重载重写重定义
- 长微博图片制作(无水印)
- AVD Manager
- 在ASP.NET 2.0中操作数据之四十三:DataList和Repeater数据排序(二)
- IDEA Java/Scala混合项目maven打包
- JAVA-反射学习(3)