您的位置:首页 > 其它

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

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: