网络流24题 ——运输问题 luogu 4015
生活随笔
收集整理的這篇文章主要介紹了
网络流24题 ——运输问题 luogu 4015
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述:這里
題面已經提示我們這是費用流了
那么由源點向所有倉庫連邊,容量為倉庫原有貨物量,費用為0
然后由所有零售商店向匯點連邊,容量為一個零售商店的需求量,費用為0
最后由倉庫向零售商店連邊,容量正無窮(由于源點和匯點的限制,所以不會出現不合法情況),費用為題給費用
然后跑費用流就得到了最小費用
至于最大費用,按套路所有費用取反后再跑一遍費用流即可
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
const int inf=0x3f3f3f3f;
struct Edge
{
int next;
int to;
int val;
int pri;
}edge[40005];
int head[255];
int dis[255];
int pre[255];
int fa[255];
bool used[255];
int lim[255];
int v1[255];
int v2[255][255];
int cnt=1;
int st,ed;
int n,m;
void init()
{
memset(head,-1,sizeof(head));
memset(edge,0,sizeof(edge));
cnt=1;
}
void add(int l,int r,int w,int v)
{
edge[cnt].next=head[l];
edge[cnt].to=r;
edge[cnt].val=w;
edge[cnt].pri=v;
head[l]=cnt++;
}
int ide(int x)
{
return (x&1)?x+1:x-1;
}
bool spfa()
{
memset(dis,0x3f,sizeof(dis));
memset(used,0,sizeof(used));
memset(lim,0,sizeof(lim));
dis[st]=0;
pre[ed]=-1;
lim[st]=inf;
used[st]=1;
queue <int> M;
M.push(st);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
{
lim[to]=min(lim[u],edge[i].val);
dis[to]=dis[u]+edge[i].pri;
pre[to]=i,fa[to]=u;
if(!used[to])used[to]=1,M.push(to);
}
}
used[u]=0;
}
return pre[ed]!=-1;
}
int EK()
{
int maxw=0,minv=0;
while(spfa())
{
maxw+=lim[ed];
minv+=lim[ed]*dis[ed];
int temp=ed;
while(temp!=st)
{
edge[pre[temp]].val-=lim[ed];
edge[ide(pre[temp])].val+=lim[ed];
temp=fa[temp];
}
}
return minv;
}
int main()
{
init();
scanf("%d%d",&n,&m);
st=m+n+1,ed=m+n+2;
for(int i=1;i<=n;i++)
{
scanf("%d",&v1[i]);
add(st,i,v1[i],0);
add(i,st,0,0);
}
for(int i=1;i<=m;i++)
{
scanf("%d",&v1[i+n]);
add(i+n,ed,v1[i+n],0);
add(ed,i+n,0,0);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&v2[i][j+n]);
add(i,j+n,inf,v2[i][j+n]);
add(j+n,i,0,-v2[i][j+n]);
}
}
printf("%d\n",EK());
init();
for(int i=1;i<=n;i++)
{
add(st,i,v1[i],0);
add(i,st,0,0);
}
for(int i=1;i<=m;i++)
{
add(i+n,ed,v1[i+n],0);
add(ed,i+n,0,0);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
add(i,j+n,inf,-v2[i][j+n]);
add(j+n,i,0,v2[i][j+n]);
}
}
printf("%d\n",-EK());
return 0;
}
總結
以上是生活随笔為你收集整理的网络流24题 ——运输问题 luogu 4015的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 95自动步枪的校枪方式是什么样的啊?
- 下一篇: js难点之闭包理解