zoukankan      html  css  js  c++  java
  • 网络流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
    ",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
    ",-EK());
    	return 0;
    }
    

      

  • 相关阅读:
    [转 scrum] Scrum的三个物件
    [转 scrum] 敏捷误解之无计划
    [转 scrum] Scrum三个角色及其职责介绍
    [转 scrum] Scrum的三个物件
    [转 scrum] Scrum三个角色及其职责介绍
    [转 scrum] Scrum术语字典
    浅尝异步IO
    LINUX内核内存屏障
    在C/C++程序里打印调用栈信息
    Ubuntu10.04下Linux内核编译的完整步骤
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10763144.html
Copyright © 2011-2022 走看看