您的位置:首页 > 其它

codevs1033 蚯蚓的游戏问题 裸最小费用最大流,注意要拆点

2015-12-07 19:08 417 查看
因为蚯蚓走过的路径不能重合,所以把每个点拆成两个点,容量赋为1,保证不会走过相同的点,再加超级源点(程序中为1)和一个辅助点(程序中为2)容量赋为k来控制蚯蚓的数量,最后汇集到一个超级汇点上。做一遍最小费用最大流即可。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct charge{
int u,v,cost,c,next;
}f[50000];
int n,m,k,num=2,cnt=0,point[3003],q[50000],pre[3003],dist[3003];
bool vis[3003];
void insect(int x,int y,int co,int bei)
{
f[cnt].u=x;f[cnt].v=y;f[cnt].cost=bei;f[cnt].c=co;
f[cnt].next=point[x];point[x]=cnt++;
f[cnt].u=y;f[cnt].v=x;f[cnt].cost=-bei;f[cnt].c=0;
f[cnt].next=point[y];point[y]=cnt++;
}
bool spfa(int begin,int end)
{
int mp,a,b,head=0,tail=0;
memset(q,0,sizeof(q));
memset(pre,0xff,sizeof(pre));
memset(dist,0x7f,sizeof(dist));
memset(vis,0,sizeof(vis));
q[0]=begin; dist[begin]=0; vis[begin]=1;
while (head<=tail)
{
a=q[head];
vis[a]=0;
mp=point[a];
while (mp>=0)
{
if (f[mp].c>0){
b=f[mp].v;
if (dist[b]>dist[a]+f[mp].cost)
{
dist[b]=dist[a]+f[mp].cost;
pre[b]=mp;
if (!vis[b]){vis[b]=1;tail++;q[tail]=b;}
}
}
mp=f[mp].next;
}
head++;
}
return dist[end]!=2139062143;
}
int MCMF(int begin,int end)
{
int ans=0,mp,i,flow,flowsum=0;
while (spfa(begin,end))
{
flow=2139062143;
for (i=pre[end];i!=-1;i=pre[f[i].u])
if (f[i].c<flow) flow=f[i].c;
for (i=pre[end];i!=-1;i=pre[f[i].u])
{
f[i].c-=flow;
f[i^1].c+=flow;
}
ans+=dist[end];
flowsum+=flow;
}
return ans;
}
int main()
{
scanf("%d %d %d\n",&n,&m,&k);
int i,a,b,c,j,ff;
memset(point,0xff,sizeof(point));
insect(1,2,k,0);
for (i=1;i<=m;++i)
{
scanf("%d",&c); num+=2;
insect(2,num-1,1,0); insect(num-1,num,1,-c);
}
ff=4;
for (i=2;i<=n;++i)
{
for (j=1;j<=m+i-1;++j)
{
scanf("%d",&c); num+=2;
if (j>1) insect(ff-2,num-1,1,0);
if (j<m+i-1) insect(ff,num-1,1,0);
insect(num-1,num,1,-c);
ff+=2;
}
ff=num+2-(m+i-1)*2;
}
for (i=1;i<=m+n-1;++i)
insect(num-(m+n-1)*2+i*2,num+1,1,0);
num++;
printf("%d\n",-1*MCMF(1,num));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: