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

luogu4015: 运输问题(网络流/最小费用最大流/最大费用最大流)

2018-03-23 15:16 1336 查看
题目链接
裸题,不用思考构图。
题目大意:
1 一个二分图,x集合是仓库,y集合是店面,每个x都通全部的y;
2 求:将x集合中全部的货物转移到y集合,最小费用和最大费用分别是多少。
解题思路:
1 网络流最难的一直是构图,但这题的图非常简单;
2 构图思路:(源点-〉x集合), (y集合 -〉汇点) ,( x-〉y);
3 最小费用最大流不难,直接用spfa来分层,然后回溯封路就好;
4 最大费用最大流:把费用取负,然后就变成了最小费用了~~输出取反就好!!
5 ps:对于点的结构体,多了一个c参数,为了推流量的时候用的。
上代码:#include<cstdio>
#include<algorithm>
using namespace std;
const int inf=999999999;
int n,m,st,ed,len,tou,wei;
int na[110],nb[110],nc[110][110],l[50005];

struct nodx{int h,f,d,v,x,c;}a[500];
struct nodb{int x,y,c,d,gg,f;}b[50005];

void ins(int x,int y,int c,int d)
{
len++;b[len].x=x;b[len].y=y;b[len].c=c;b[len].d=d;
b[len].gg=a[x].h;a[x].h=len;b[len].f=len+1;
len++;b[len].x=y;b[len].y=x;b[len].c=0;b[len].d=-d;
b[len].gg=a[y].h;a[y].h=len;b[len].f=len-1;
}

void bt(int k)//构图函数
{
len=0;
for(int i=st;i<=ed;i++) a[i].h=0;

for(int i=1;i<=m;i++) ins(st,i,na[i],0); //st->仓库
for(int i=1;i<=n;i++) ins(i+m,ed,nb[i],0);//店面->ed

for(int i=1;i<=m;i++)//仓库->店面
{
for(int j=1;j<=n;j++)
{
ins(i,j+m,na[i],nc[i][j]*k); //从x->y最多的数量 就是 x 有的数量
}
}
}

bool spfa()
{
for(int i=0;i<=ed;i++) { a[i].v=0;a[i].d=inf; }
a[st].v=1;a[st].d=0;a[st].c=inf;
l[1]=st;tou=1;wei=2;
while(tou!=wei)
{
int x=l[tou];
for(int i=a[x].h;i>0;i=b[i].gg)
{
int y=b[i].y;
if(a[y].d>a[x].d+b[i].d&&b[i].c>0)
{
a[y].d=a[x].d+b[i].d;
a[y].x=x;//记录来时的x
a[y].f=i;//记录来时的路
a[y].c=min(a[x].c,b[i].c);//记录该点获取的流量
if(a[y].v==0)
{
a[y].v=1;l[wei++]=y;if(wei>ed) wei=1;
}
}
}
a[x].v=0; tou++; if(tou>ed)tou=1;
}
if(a[ed].d!=inf)
{
for(int x=ed;x!=st;x=a[x].x)//把整条路的流量更改(封路)
{
int i=a[x].f;
b[i].c-=a[ed].c;
b[b[i].f].c+=a[ed].c;
}
return 1;
}
return 0;
}

int flow()
{
int ans=0;
while(spfa())
{
ans+=a[ed].c*a[ed].d;//流量*单价
}
return ans;
}

int main()
{
scanf("%d %d",&m,&n);int x,y;
st=0;ed=n+m+1;

for(int i=1;i<=m;i++) scanf("%d",&na[i]);
for(int i=1;i<=n;i++) scanf("%d",&nb[i]);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&nc[i][j]);
}
}

bt(1);//先构最小费用的图
printf("%d\n",flow());

bt(-1);//再构最大费用的图
printf("%d\n",-flow()); //输出取反

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐