• URAL 1076 Trash 【最大权匹配KM快速模板O(N^3)】


    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1076

    我的链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=19651#problem/H


    1076. Trash

    Time Limit: 1.0 second
    Memory Limit: 16 MB

    Description

    You were just hired as CEO of the local junkyard.One of your jobs is dealing with the incoming trash and sorting it for recycling.The trash comes every day in N containers and each of these containers contains certain amount of each of the N types of trash. Given the amount of trash in the containers find the optimal way to sort the trash. Sorting the trash means putting every type of trash in separate container. Each of the given containers has infinite capacity. The effort for moving one unit of trash from container i to j is 1 if i ≠ j otherwise it is 0.You are to minimize the total effort.

    Input

    The first line contains the number N (1 ≤ N ≤ 150), the rest of the input contains the descriptions of the containers.The (1 + i)-th line contains the description of the i-th container the j-th amount (0 ≤ amount ≤ 100) on this line denotes the amount of the j-th type of trash in the i-th container.

    Output

    You should write the minimal effort that is required for sorting the trash.

    Sample Input

    input output
    4
    62 41 86 94
    73 58 11 12
    69 93 89 88
    81 40 69 13
    
    650


    题意:

         你受聘于当地的垃圾处理公司任CEO,你的一项工作是处理引进的垃圾,以及分类垃圾以进行循环利用。每天,垃圾会有几个集装箱运来,每一个集装箱都包含几种垃圾。给定集装箱里垃圾的数目n,请找出最佳的途径去分类这些垃圾。分类垃圾即把每种垃圾分开装到不同的集装箱中。每个集装箱的容量都是无限的。搬动一个单位的垃圾需要耗费代价,从集装箱i到j是1(i≠j,否则代价为0),你必须把代价减到最小。

    思路:

    求最大权匹配的KM算法,只需把所有边的权值取相反数,求最大权匹配,结果再取相反数即可。

    把垃圾筒作为点集u,垃圾总类作为点集v,建图w[i][j]表示把j类垃圾放入i 桶的代价。

    分析:用前面的KM模板时间复杂度为O(N^4)容易超时。

               前面的版本修改顶标:

                    枚举s和t中的每一个元素,根据定义计算最小值,每次修时间为O(N^2),总时间为O(N^4).

              快速修改顶标法:

                    给t中的每个节点y定义松弛量。slack(y) = min{ l[x]+l[y]-w[x][y] }

                    则a变为a = min{ slack(y)| y in t`}

                    计算所有slack要O(N)时间。每次增广后最多修改N次顶标,所以每次增广后修改顶标总时间为O(N^2),程序总时间降为O(N^3).

    //Accepted	216 KB	31 ms	C++	1503 B	2013-02-26 20:03:10
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=155;
    const int inf=1000;
    int w[maxn][maxn];
    int lx[maxn],ly[maxn]; //顶标 
    bool s[maxn],t[maxn];
    int match[maxn];
    int slack[maxn]; //点集v的松弛量 
    int n;
    bool hungary(int u)
    {
    	s[u] = true;
    	for(int v=1;v<=n;v++)
    	{
    		if(!t[v] && lx[u]+ly[v] == w[u][v])
    		{
    			t[v] = true;
    			if(match[v]==-1 || hungary(match[v]))
    			{
    				match[v]=u;
    				return true;
    			}
    		}
    		else if(slack[v] > lx[u]+ly[v]-w[u][v])//修改松弛量 
    			slack[v] = lx[u]+ly[v]-w[u][v];
    	}
    	return false;
    }
    int KM()
    {
    	int sum=0;
    	memset(match,-1,sizeof(match));
    	memset(ly,0,sizeof(ly));
    	for(int i=1;i<=n;i++)
    	{
    		lx[i]= -inf;
    		for(int j=1;j<=n;j++)
    			lx[i]=max(lx[i],w[i][j]);
    	}	
    	for(int i=1;i<=n;i++)
    	{
    		while(true)
    		{
    			memset(s,false,sizeof(s));
    			memset(t,false,sizeof(t));
    			for(int j=1;j<=n;j++)
    				slack[j]=inf;
    			if(hungary(i)) break;
    			else
    			{
    				int a=inf;
    				for(int j=1;j<=n;j++)
    					if(!t[j] && slack[j]<a)
    						a=slack[j];
    				for(int j=1;j<=n;j++)
    				{
    					if(s[j]) lx[j]-=a;
    					if(t[j]) ly[j]+=a;
    				}
    			}
    		}
    	}
    	for(int i=1;i<=n;i++) sum+=w[match[i]][i];
    	return sum;		 
    }
    int main()
    {
    	int weight;
    	while(scanf("%d",&n)!=EOF)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			weight=0;
    			for(int j=1;j<=n;j++)
    			{
    				scanf("%d",&w[i][j]);
    				weight+=w[i][j];
    			}
    			for(int j=1;j<=n;j++)
    				w[i][j]=weight-w[i][j];
    		}
    		for(int i=1;i<=n;i++)
    		{
    			for(int j=1;j<=n;j++)
    				w[i][j] = -w[i][j];
    		}	
    		printf("%d\n",-KM());
    	}
    	return 0;
    } 
    
      	 
  • 相关阅读:
    解决Prism的EventAggregator的事件订阅错误
    解决Prism中Region的GetView不起作用问题
    怎样成为一个高手
    排球比赛积分规则
    个人作业
    个人作业
    会议总结
    个人总结
    本周冲刺
    本周个人总结
  • 原文地址:https://www.cnblogs.com/freezhan/p/2950437.html
Copyright © 2020-2023  润新知