• hdu 2686 最小费用最大流


    #include "stdio.h" //hdu 2686 最小费用最大流
    #include "string.h"
    #include "queue"
    using namespace std;
    
    #define N 2005
    #define INF 0x3fffffff
    
    struct node {
    	int u,v,w,k;
    	int next;
    }edge[4*N*10];
    
    int n,ans,idx;
    bool mark[N];
    int head[N],dis[N],route[N];
    
    void init();
    int SPFA(int start,int end);
    void EK(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 i,j;
    	int w,k,u,v;
    	while(scanf("%d",&n)!=-1)
    	{
    		init();
    		k = n*n;
    		for(i=1;i<=n;i++)
    		{
    			for(j=1;j<=n;j++)
    			{
    				u = j+(i-1)*n;
    				scanf("%d",&w);
    				adde(u,u+k,-w,1);  //因为求最大费用流,故取反
    				if(j!=n)	adde(u+k,u+1,0,INF);
    				if(i!=n)	adde(u+k,u+n,0,INF);
    			}
    		}
    		int start=0,end = 2*n*n+1;
    		adde(start,1,0,2);
    		adde(1,k+1,0,1);  //为1->n*n再添一条边,花费为0
    		adde(2*k,end,0,2);
    		adde(k,2*k,0,1); //为n*n->2*n*n再添一条边,花费为0
    		while(SPFA(start,end))
    			EK(start,end);
    		printf("%d
    ",-ans);
    	}
    	return 0;
    }
    
    void init()   //初始化
    {
    	ans = 0;
    	idx = 0;
    	memset(head,-1,sizeof(head));
    }
    
    void adde(int u,int v,int w,int k)
    {
    	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)   //自己的理解,带负权的图中,能用SPFA算法,是因为本题中没有带负权的环!
    {
    	int i;
    	for(i=0;i<=end;i++) dis[i] = INF;
    	memset(mark,false,sizeof(mark));
    	memset(route,-1,sizeof(route));
    	dis[start] = 0;
    	queue<int> q;
    	q.push(start);
    	mark[start] = true;
    	int x,y;
    	while(!q.empty())
    	{
    		x = q.front();
    		q.pop();
    		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;
    				if(mark[y] == false)
    				{
    					mark[y] = true;
    					q.push(y);
    				}
    			}
    		}
    		mark[x] = false;
    	}
    	if(route[end]==-1) return 0;
    	return 1;
    }
    
    void EK(int start,int end)  
    {
    	int x,y=route[end];
    	while(y!=-1)
    	{
    		x = y^1;
    		edge[y].k--;
    		edge[x].k++;
    		ans += edge[y].w*s;
    		y = route[edge[y].u];
    	}
    }
    

  • 相关阅读:
    关于Android线程间通信
    关于代码重构
    Android读书笔记01
    回忆 2012年写的
    我的笑 -- 2007年写的?
    伊人笑 2010年
    血色青春 2012年
    隔夜听雨
    错乱的爱 2010年
    【前端JS、后台C#】编码解码。
  • 原文地址:https://www.cnblogs.com/ruo-yu/p/4412000.html
Copyright © 2020-2023  润新知