hdu 4309(最大流+枚举状态)
2013-05-05 12:54
375 查看
题目链接: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
思路:2^12枚举修复哪些桥,不修复的桥没有花费,连接的边流量为1,要修复的桥则计算花费,边的流量为无穷,建立最大流模型来求解,增加一个源点S(0),和一个汇点T(n+1)。S向每个有人的点,连一条容量为人数的边,图中普通的u->v的有向边,连一条u->v的流量为无穷的边,对于u->v的隧道,可以连接u->v的流量无穷的边,和u->T的流量为隧道人数上限的边,求解最大流即可;
ps:枚举状态用递归即可。
View Code
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXN 222 #define MAXM 3333 #define inf 1<<30 struct Edge{ int v,cap,next; }edge[MAXM],E[MAXM]; struct ReEdge{ int index,cap; }reedge[MAXM]; int head[MAXN]; int cur[MAXN]; int pre[MAXN]; int level[MAXN]; int gap[MAXN]; int NV,NE,vs,vt,n,m,total,mincost,maxnum; void Insert(int u,int v,int cap,int cc=0){ edge[NE].v=v;edge[NE].cap=cap; edge[NE].next=head[u];head[u]=NE++; edge[NE].v=u;edge[NE].cap=cc; edge[NE].next=head[v];head[v]=NE++; } int SAP(int vs,int vt){ memset(pre,-1,sizeof(pre)); memset(level,0,sizeof(level)); memset(gap,0,sizeof(gap)); for(int i=0;i<=n+1;i++)cur[i]=head[i]; int u=pre[vs]=vs,maxflow=0,aug=-1; gap[0]=NV; while(level[vs]<NV){ loop: for(int &i=cur[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(edge[i].cap&&level[u]==level[v]+1){ aug==-1?aug=edge[i].cap:aug=min(aug,edge[i].cap); pre[v]=u; u=v; if(v==vt){ maxflow+=aug; for(u=pre[u];v!=vs;v=u,u=pre[u]){ edge[cur[u]].cap-=aug; edge[cur[u]^1].cap+=aug; } aug=-1; } goto loop; } } int minlevel=NV; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(edge[i].cap&&minlevel>level[v]){ cur[u]=i; minlevel=level[v]; } } gap[level[u]]--; if(gap[level[u]]==0)break; level[u]=minlevel+1; gap[level[u]]++; u=pre[u]; } return maxflow; } void Solve(int num,int cost){ if(num>=total){ for(int i=0;i<NE;i+=2){ edge[i].cap+=edge[i^1].cap; edge[i^1].cap=0; } int ans=SAP(vs,vt); if(ans>maxnum){maxnum=ans;mincost=cost;} else if(ans==maxnum&&mincost>cost){ mincost=cost;} }else { Solve(num+1,cost); edge[reedge[num].index].cap=inf; Solve(num+1,cost+reedge[num].cap); edge[reedge[num].index].cap=1; edge[reedge[num].index^1].cap=0; } } int main(){ int city_num,u,v,w,p; while(~scanf("%d%d",&n,&m)){ vs=0,vt=n+1,NV=n+2,NE=0,total=0,mincost=inf,maxnum=0; memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++){ scanf("%d",&city_num); Insert(vs,i,city_num); } for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&u,&v,&w,&p); if(p==0)Insert(u,v,inf); else if(p<0){Insert(u,vt,w);Insert(u,v,inf);} else { reedge[total].index=NE; reedge[total++].cap=w; Insert(u,v,1); } } Solve(0,0); if(!maxnum)puts("Poor Heaven Empire"); else printf("%d %d\n",maxnum,mincost); } return 0; }
相关文章推荐
- HDU 4309 Seikimatsu Occult Tonneru(最大流SAP+状态压缩枚举)
- hdu 4309(最大流+枚举状态)
- HDU 4309 Seikimatsu Occult Tonneru (枚举+最大流)
- HDU 4309 Seikimatsu Occult Tonneru(网络流+枚举状态)
- hdu 4309 Seikimatsu Occult Tonneru(枚举+最大流)
- HDU 4309 Seikimatsu Occult Tonneru(最大流+二进制枚举)
- hdu 4309 Seikimatsu Occult Tonneru 枚举+最大流
- HDU 2870 Largest Submatrix (求最大子矩阵变形,可变值)枚举每种情况
- hdu 4309 状压+最大流
- HDU 4354 Missile 树的最大独立集+枚举
- HDU 4309 Seikimatsu Occult Tonneru(网络流-最大流)
- hdu 5556 Land of Farms【思维+暴力枚举+最大独立集】好题!
- 【HDU - 3605 】Escape 【状态压缩 构图+最大流 or 多重匹配】
- hdu 3605 Escape 状态压缩+最大流
- hdu 4309 状压+最大流
- hdu 4433 locker(动态规划:枚举状态)
- hdu 1281 棋盘游戏(枚举,二分图最大匹配)
- HDU 1281——棋盘游戏——————【最大匹配、枚举删点、邻接表方式】
- HDU 3605 Escape(状态压缩+最大流)
- hdu 3081 【二分匹配+并查集+删边||最大路+并查集+二分枚举】