题解 洛谷P4014 网络流24题.05 【分配问题】

\(\huge\mathbb{DESCRIPTION}\)
编号:洛谷\(4014\)\(LOJ6012\)(与洛谷上本题完全相同)
算法:最小费用最大流\(\mathbb{OR}\)二分图
来源:网络流\(24\)
\(\huge\mathbb{SOLUTION}\)
这道题目来自网络流\(24\)题。
我们仍然不用网络流做。
事实上,看到这道题,我们就应该能够想到二分图
其实,这还算是一道比较裸的二分图
首先,我们把人和工程放在两边,把效率当作边权来看,这样二分图就建好了。
然后,我们利用匈牙利算法进行简单的求解。
看似时间复杂度很高,是\(O(N^4)\),跑的倒也挺快的。
关键点在于,题目求的是最大值,我们不妨对边权全体取相反数,再求最小值即可。
这大概是个常规套路吧
\(\huge\mathbb{CODE}\)

#include<bits/stdc++.h>
using namespace std;
int N;
int Time[101][101];
int Match[101];
int S[101],T[101];
int X[101],Y[101];
inline bool Dfs(int Now)
{
    register int i;
    S[Now]=true;
    for(i=1;i<=N;i++)
    {
        if(X[Now]+Y[i]==Time[Now][i]&&!T[i])
        {
            T[i]=true;
            if(!Match[i]||Dfs(Match[i]))
            {
                Match[i]=Now;
                return true; 
            } 
        }
    }
    return false;
}
inline void Update()
{
	register int i,j;
	register int Max;
	Max=2147483647;
	for(i=1;i<=N;i++)
	{
		if(S[i])
		{
			for(j=1;j<=N;j++)
			{
				if(!T[j])
				{
					Max=min(Max,X[i]+Y[j]-Time[i][j]);
				}
			}
		}
	}
	for(i=1;i<=N;i++)
	{
		if(S[i])
		{
			X[i]+=Max;
		}
		if(T[i])
		{
			Y[i]-=Max;
		}
	}
}
inline void Hungary()
{
	register int i,j;
	for(i=1;i<=N;i++)
	{
		Match[i]=0;
		X[i]=0;
		Y[i]=0;
		for(j=1;j<=N;j++)
		{
			X[i]=max(X[i],Time[i][j]); 
		}
	}
	for(i=1;i<=N;i++)
	{
		while(true)
		{
			for(j=1;j<=N;j++)
			{
				S[j]=false;
				T[j]=false;
			}
			if(Dfs(i))
			{
				break;
			}
			else
			{
				Update();
			}
		}
	}
}
int main(void)
{
	register int i,j;
	cin>>N;
	for(i=1;i<=N;i++)
	{
		for(j=1;j<=N;j++)
		{
			cin>>Time[i][j];
		}
	}
	register int Sum1;
	register int Sum2;
	Sum1=Sum2=0;
	Hungary();
	for(i=1;i<=N;i++)
	{
		Sum1+=X[i];
		Sum1+=Y[i];
	}
	for(i=1;i<=N;i++)
	{
		for(j=1;j<=N;j++)
		{
			Time[i][j]=-Time[i][j];
		}
	}
	Hungary();
	for(i=1;i<=N;i++)
	{
		Sum2+=X[i];
		Sum2+=Y[i];
	}
	cout<<-Sum2<<endl<<Sum1<<endl;
	return 0;
}

posted @ 2020-08-16 23:33  Bushuai_Tang  阅读(173)  评论(1编辑  收藏  举报