【hdu2055】奔小康赚大钱(最佳匹配)
Problem Description
传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。
这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。
另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).
这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。
另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).
Input
输入数据包含多组测试用例,每组数据的第一行输入n,表示房子的数量(也是老百姓家的数量),接下来有n行,每行n个数表示第i个村名对第j间房出的价格(n<=300)。
Output
请对每组数据输出最大的收入值,每组的输出占一行。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define re return #define ll long long #define inc(i,l,r) for(int i=l;i<=r;++i) const int inf=2147483647,maxn=305; using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } int n; int ex1[maxn];//1的期望度 int ex2[maxn];//2的期望度 int pri[maxn][maxn];//价格 int match[maxn];//匹配2的1 int vis1[maxn];//1是否被访问过 int vis2[maxn];//2是否访问过 int slack[maxn];//最小差多少,2可以被1访问 inline bool dfs(int x) { vis1[x]=1;//标记1访问 inc(i,1,n) { if(vis2[i])continue; if(ex1[x]+ex2[i]==pri[x][i])//达到访问要求 { vis2[i]=1;标记2访问 if(!match[i]||dfs(match[i])) { match[i]=x; re 1; } } else slack[i]=min(slack[i],ex1[x]+ex2[i]-pri[x][i]); //2差值统计 } re 0; } inline void KM() { inc(i,1,n)match[i]=ex2[i]=0; //刷新 inc(i,1,n) { inc(j,1,n) slack[j]=inf; while(2333) { inc(j,1,n)vis1[j]=vis2[j]=0; if(dfs(i))break; int d=inf; inc(j,1,n) if(!vis2[j]) d=min(d,slack[j]); //最小改变度 inc(j,1,n) { if(vis1[j])ex1[j]-=d; if(vis2[j])ex2[j]+=d; else slack[j]-=d; //分别改变 } } } } int main() { while(~scanf("%d",&n)) { inc(i,1,n)ex1[i]=-inf; inc(i,1,n) inc(j,1,n) { rd(pri[i][j]); ex1[i]=max(ex1[i],pri[i][j]); } int ans=0; KM(); for(int i=1;i<=n;++i) ans+=pri[match[i]][i]; printf("%d\n",ans); } re 0; }