题解 洛谷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;
}
不要妄图追上西坠的太阳,而是要在黎明前就等着它!