您的位置:首页 > 理论基础 > 计算机网络

[网络流] bzoj1834: [ZJOI2010]network 网络扩容

2018-03-21 17:20 323 查看
bzoj1834: [ZJOI2010]network 网络扩容 http://www.lydsy.com/JudgeOnline/problem.php?id=1834

最大流+费用流

第一问直接跑最大流这个很简单

第二问好像很复杂的样纸……

因为原来的图里面有残余的流量所以如果把这些流量也能用上的话费用就会小很多

所以直接在原来跑完最大流的图的基础上再建上容量为k费用为w的边

再建多一个超级汇源 边的容量为k 限制增加流量为k

然后跑费用流就可以了

不看题解真的不会做

机房大佬的题解:https://www.cnblogs.com/Never-mind/p/8150382.html

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node1
{
int x,y,c,cost,next,other;
}a[21000];
int last[1100],len;
int x[5100],y[5100],c[5100],w[5100];
int dep[11000],f[11000],pre[11000];
int st,ed,edx,list[1100000];
bool v[1100];
int ans=0;
void build(int x,int y,int c,int cost)
{
len++;int k1=len;
a[len].x=x;a[len].y=y;a[len].c=c;a[len].cost=cost;a[len].next=last[x];last[x]=len;
len++;int k2=len;
a[len].x=y;a[len].y=x;a[len].c=0;a[len].cost=-cost;a[len].next=last[y];last[y]=len;
a[k1].other=k2;a[k2].other=k1;
}
bool bfs()
{
memset(dep,0,sizeof(dep));
int head=1,tail=1;
list[1]=st;dep[st]=1;
while (head<=tail)
{
int x=list[head];
for (int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if (dep[y]==0&&a[k].c>0)
{
dep[y]=dep[x]+1;
list[++tail]=y;
}
}
head++;
}
if (dep[ed]==0) return 0;
else return 1;
}
int dfs(int x,int flow)
{
if (x==ed) return flow;
int tot=0,sum=0;
for (int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if (dep[y]==dep[x]+1&&a[k].c>0&&flow>tot)
{
sum=dfs(y,min(flow-tot,a[k].c));
tot+=sum;a[k].c-=sum;a[a[k].other].c+=sum;
}
}
if (tot==0) dep[x]=0;
return tot;
}
bool spfa()
{
memset(v,false,sizeof(v));
memset(f,63,sizeof(f));
int head=1,tail=1;
list[1]=st;v[st]=true;
f[st]=0;
while (head<=tail)
{
int x=list[head];
for (int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if (f[y]>f[x]+a[k].cost&&a[k].c>0)
{
f[y]=f[x]+a[k].cost;
pre[y]=k;
if (v[y]==false)
{
v[y]=true;
list[++tail]=y;
}
}
}
head++;
v[x]=false;
}
if (f[edx]>=999999999) return false;
else
{
int x=edx,minn=999999999;
ans+=f[edx];
while (x!=st)
{
int k=pre[x];
a[k].c--;
a[a[k].other].c++;
x=a[k].x;
}
return true;
}
}
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x[i],&y[i],&c[i],&w[i]);
build(x[i],y[i],c[i],0);
}
st=n+1;ed=n+2;
build(st,1,999999999,0);
build(n,ed,999999999,0);
while (bfs())
{
ans+=dfs(st,999999999);
}
printf("%d ",ans);
for (int i=1;i<=m;i++)
{
build(x[i],y[i],k,w[i]);
}
edx=ed+1;
build(n,edx,k,0);//限制为k
ans=0;
while (spfa()) {}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: