zoukankan      html  css  js  c++  java
  • poj2516 最小费用最大流

    #include "stdio.h"  // 最小费用最大流 poj 2516
    #include "string.h"
    #include "queue"
    using namespace std;
    #define N 115
    #define INF 1000000000
    
    struct node {
    	int u,v,w,k;
    	int next;
    }edge[8*N*N];
    
    int store[N];
    int n,m,k,ans,idx;
    int head[N],dis[N],route[N],mark[N];
    int shop[N][N],supply[N][N],cost[N][N];
    
    void init();
    void EK(int start,int end);  
    int SPFA(int start,int end);  
    void adde(int u,int v,int w,int k);  
    void addedge(int u,int v,int w,int k);  
    
    int main()
    {
    	int sum;
    	int i,j,tt;
    	int sum1[N],sum2[N];
    	while(scanf("%d %d %d",&n,&m,&k))
    	{
    		tt=k;
    		if(n==0 && m==0 && k==0)	return 0;
    		memset(sum1,0,sizeof(sum1));
    		memset(sum2,0,sizeof(sum2));
    		for(i=1;i<=n;i++)
    		{
    			for(j=1;j<=k;j++)
    			{
    				scanf("%d",&shop[i][j]);
    				sum1[j]+=shop[i][j];  //N家商店需要第j件物品的总件数
    			}
    		}
    		for(i=1;i<=m;i++)
    		{
    			for(j=1;j<=k;j++)
    			{
    				scanf("%d",&supply[i][j]);
    				sum2[j]+=supply[i][j];   //M处仓库供应第j件物品的总件数
    			}
    		}
    		sum = 0;   //答案初始化(sum记录结果)
    		bool flag=true;
    		for(tt=1;tt<=k;tt++)
    		{
    			if(sum1[tt]>sum2[tt]) 
    				flag=false;
    			init();
    			int start=0,end=n+m+1;
    			for(i=1;i<=n;i++)
    			{
    				for(j=1;j<=m;j++)
    				{
    					scanf("%d",&cost[i][j]);
    					adde(j,i+m,cost[i][j],INF);
    				}
    			}
    			for(j=1;j<=m;j++)
    				adde(start,j,0,supply[j][tt]);
    			for(i=1;i<=n;i++)
    			{
    				store[i] = idx;
    				adde(i+m,end,0,shop[i][tt]);
    			}
    			while(SPFA(start,end))
    				EK(start,end);
    			sum += ans;
    		}
    		if(flag==false)
    			printf("-1
    ");
    		else
    			printf("%d
    ",sum);
    	}
    	return 0;
    }
    
    void init()
    {
    	ans = 0;
    	idx = 0;
    	memset(head,-1,sizeof(head));
    }
    
    void adde(int u,int v,int w,int k)  //对其中的一条再加上一条流量为0的回路  
    {  
        addedge(u,v,w,k);  
        addedge(v,u,-w,0);  
    }  
      
    void addedge(int u,int v,int w,int k)  //邻接表建边  
    {  
        edge[idx].u = u;  
        edge[idx].v = v;  
        edge[idx].w = w;  
        edge[idx].k = k;  
        edge[idx].next = head[u];  
        head[u] = idx;  
        idx++;  
    }  
    
    int SPFA(int start,int end)  //找一条存在流量的最小费用流(存在流量就行)  
    {  
        int i;  
        memset(mark,false,sizeof(mark));  //初始化标记数组mark[];  
        memset(route,-1,sizeof(route));   //ruote[]记录流量路径(存下一条边的下标)  
        for(i=start;i<=end;i++)      dis[i] = INF;  
        dis[start] = 0;  
        queue<int> q;  
        q.push(start);  
        mark[start] = true;  
        int x,y;  
        while(!q.empty())  
        {  
            x = q.front();  
            for(i=head[x];i!=-1;i=edge[i].next)  
            {  
                y = edge[i].v;  
                if(edge[i].k && dis[y] > dis[x] + edge[i].w)  
                {  
                    dis[y] = dis[x] + edge[i].w;  
                    route[y] = i;   //route[]里面存的为边的下标  
                    if(mark[y] == false)  
                    {   
                        mark[y] = true;  
                        q.push(y);  
                    }  
                }  
            }  
            q.pop();  
            mark[x] = false;  //对出队列的点的标记还原  
        }  
        if(dis[end] == INF) return 0;  
        return 1;  
    }  
      
    void EK(int start,int end)  
    {  
    	int s=INF;
        int x,y;  
    	y = route[end];
    	while(y!=-1)
    	{
    		if(s>edge[y].k)
    			s = edge[y].k;
    		y = route[edge[y].u];
    	}
        y = route[end];  
        while(y!=-1)  
        {  
            x = y^1;  //很特别的处理;  
            edge[y].k -= s;  //对流量进行处理(正减反加)  
            edge[x].k += s;  
            ans += edge[y].w*s;  
            y = route[edge[y].u]; //通过route[]访问路径上的下一个节点  
        }
    }  

  • 相关阅读:
    三比三:无线监控优点与传输技术剖解
    手把手教你学习FPGA系列视频教程_救护车鸣笛声
    世纪大争论:Linux还是GNU/Linux?
    [分享]我的LABVIEW快速开发串口测试软件实例
    高能效系统的功耗优化技术
    python学习小脚本多用户登录
    python学习三级菜单省市选择
    python学习购物车小程序
    python学习语句总结
    python学习猜年龄小游戏
  • 原文地址:https://www.cnblogs.com/ruo-yu/p/4411996.html
Copyright © 2011-2022 走看看