标签:老百姓 can printf || str 必须 bool 分配 htm
Input输入数据包含多组测试用例,每组数据的第一行输入n,表示房子的数量(也是老百姓家的数量),接下来有n行,每行n个数表示第i个村名对第j间房出的价格(n<=300)。
Output请对每组数据输出最大的收入值,每组的输出占一行。
Sample Input
2 100 10 15 23
Sample Output
123
这是KM算法的一道模板题
KM算法就是的最大权匹配(与匈牙利算法不同的是KM需要考虑权值)
依旧是男女配对
https://www.cnblogs.com/wenruo/p/5264235.html(请参考这篇博客,很详细)
该题中的村民就相当于女生,房子就相当于男生,若尽可能多的满足大家需求,就要一次一次配对,适当降低部分人的
标准,配对过程是一个递归过程
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int maxn=310; const int inf=0x3f3f3f3f; int yuji[maxn][maxn];//记录每个村民对每个房子的所支付金额 int cunmin[maxn]; int fangzi[maxn]; bool vis_cunmin[maxn]; bool vis_fangzi[maxn]; int match[maxn]; int sla[maxn]; int n; bool dfs(int x) { vis_cunmin[x]=true; for(int f=0;f<n;f++) { if(vis_fangzi[f])continue; int g=cunmin[x]+fangzi[f]-yuji[x][f]; if(g==0) { vis_fangzi[f]=true; if(match[f]==-1||dfs(match[f])) { match[f]=x; return true; } } else { sla[f]=min(sla[f],g); } } return false; } int km() { memset(match,-1,sizeof(match)); memset(fangzi,0,sizeof(fangzi)); for(int i=0;i<n;i++) { cunmin[i]=yuji[i][0]; for(int j=1;j<n;j++) { cunmin[i]=max(cunmin[i],yuji[i][j]); } } for(int i=0;i<n;i++) { fill(sla,sla+n,inf); while(1) { memset(vis_cunmin,false,sizeof(vis_cunmin)); memset(vis_fangzi,false,sizeof(vis_fangzi)); if(dfs(i)) break; int d=inf; for(int j=0;j<n;j++) if(!vis_fangzi[j]) d=min(d,sla[j]); for(int j=0;j<n;j++) { if(vis_cunmin[j]) cunmin[j]-=d; if(vis_fangzi[j]) fangzi[j]+=d; else sla[j]-=d; } } } int res=0; for(int i=0;i<n;i++) res+=yuji[match[i]][i]; return res; } int main() { while(~scanf("%d",&n)) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&yuji[i][j]); printf("%d\n",km()); } return 0; }
标签:老百姓 can printf || str 必须 bool 分配 htm
原文地址:https://www.cnblogs.com/ylrwj/p/11794782.html