hdu 4309(最大流+枚举状态)
来源:互联网 发布:外交官 新秀丽 知乎 编辑:程序博客网 时间:2024/06/07 01:32
题目链接: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 }
0 0
- hdu 4309(最大流+枚举状态)
- HDU 4309 Seikimatsu Occult Tonneru(最大流SAP+状态压缩枚举)
- HDU 4309 Seikimatsu Occult Tonneru(网络流+枚举状态)
- hdu 4309 状压枚举+最大流
- hdu 1733(枚举+最大流)
- hdu 4309 Seikimatsu Occult Tonneru(枚举+最大流)
- hdu 4309 Seikimatsu Occult Tonneru 枚举+最大流
- HDU-4462(状态压缩,枚举)
- HDU -- 3605 Escape(最大流 状态合并判满流)
- HDU - 3605 Escape(最大流+状态压缩)
- hdu 3605_最大流 状态压缩
- hdu 3605 /状态合并最大流
- HDU 3605 Escape(最大流+状态压缩)
- hdu 3605 Escape 状态压缩+最大流
- HDU 3605 Escape(最大流+状态压缩)
- HDU 3605 Escape(最大流+状态压缩)
- hdu 3605 Escape (最大流+状态压缩)
- HDU 4610(数论+枚举状态)
- hdu 3081(二分+最大流+并查集)
- hdu 3277(最大流+二分+并查集)
- hdu 3416(最短路+最大流)
- hdu 4143
- hdu 3998(最长上升子序列及个数)
- hdu 4309(最大流+枚举状态)
- hdu 3046(最小割)
- hdu 1565+hdu 1569(最大点权独立集)
- win8下安装锐捷的兼容性问题
- hdu 4292(拆点+最大流)
- hdu 3491(最小割+拆点)
- hdu 1354
- How to estimate the time required for a program.
- hdu 1240(三维bfs)