版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢 https://blog.csdn.net/Deep_Kevin/article/details/82460087
正题
看到这个题目,会觉得可以直接用绿与被绿匈牙利算法来解决。
但是当我们遇到,“第i个人和第j个物品会产生g[i][j]的价值,求完全匹配的最小价值”的时候。
我们就需要用到二分图最优匹配的算法了。
这个算法的复杂度很高,要慎用。
那么其实也是可以用费用流来解决的,直接建边,每次跑SPFA即可。
回归主题:怎么求?
从这里开始认真看。设置两个数组,和,分别表示tx指左边,ty指右边。
我们定义当且仅当 的时候,我们才认为从i可以到j。
bool find(int x){
visx[x]=true;
for(int i=1;i<=n;i++)
if(!visy[i] && tx[x]+ty[i]==g[x][i]){//匈牙利的这一行发生改变
visy[i]=true;
if(prep[i]==0 || find(prep[i])){
prep[i]=x;
return true;
}
}
return false;
}
那么我们要向费用流那样子,每次优先走最大的边。
这样走出来的增广路是最大的。
所以,每个初始化为第i个点出边的最大,也就是。
扫描二维码关注公众号,回复:
3114088 查看本文章
这样我们走出来的是最大的。
但是可能很多个点会选择同一个点。
那怎么办呢。
我们可以让某些tx和ty改变使得可以走更多的边。
因为我们走某条边的条件,所以明显当时,那些可以走去的右节点的ty就要-=d.
目的是使得“之前的点可以走”。
我们肯定要想着变化量越小越好,所以我们在去不到的边取一个最小值。
再不断地用匈牙利增广就行了。
代码和讲解下次再更新