二分图最佳匹配-8616 汽车拉力比赛

来源:互联网 发布:js数据类型 编辑:程序博客网 时间:2024/04/30 02:32

8616 汽车拉力比赛

时间限制:500MS  内存限制:1000K
提交次数:3 通过次数:3

题型: 编程题   语言: 无限制

描述

SCAU车队要去参加汽车拉力比赛啦。拉力比赛中,每辆汽车需要一个驾驶员和一个导航员。SCAU车队一共有有N个驾驶员和N个导航员,每个 驾驶员对每个导航员有一个默契值,现在需要求得某种N对N的配对,使得这N个配对的默契值之和最大。 

Input

多Case,每一个Case第一行是一个整数N,范围是(1<=N<=16)。接下来有N行,每行有N个数,第i行第j个数表示第i个驾驶员和第j个导航员的默契值。 测试数据会有多组,当N=0时表示数据结束,这行不用处理。

Output

输出配对后默契值之和的最大值。

Sample Input

1 5 2 10 20 25 5 0  

Sample Output

5 45  

Source

CPP
这题很明显的二分图最佳匹配,很显然我不会,果断去找资料,经过理解和研究标程,已经将其纳为己用了,这就是传说中的km算法,理解有点蛋疼,因为老说什么交错树,不知道是什么东东,不过不鸟它,看代码直接自己想能想通的,下面是我的代码。。。
#include<string>#include<algorithm>#define N 100using namespace std;int gp[N][N],vx[N],vy[N],fx[N],fy[N],n,m[N];int dfs(int u){vx[u]=1;for(int i=0;i<n;i++){if(vy[i]==0&&fx[u]+fy[i]==gp[u][i]){vy[i]=1;if(m[i]==-1||dfs(m[i])){m[i]=u;return 1;}}}return 0;}int count(){int i,j,k,d,ans;for(i=0;i<n;i++){fx[i]=-0x7fffffff;fy[i]=0;for(j=0;j<n;j++){if(fx[i]<gp[i][j]){fx[i]=gp[i][j];}}}memset(m,-1,sizeof(m));for(int u=0;u<n;u++){memset(vx,0,sizeof(vx));memset(vy,0,sizeof(vy));while(!dfs(u)){d=0x7fffffff;for(i=0;i<n;i++){if(vx[i])for(j=0;j<n;j++){if(!vy[j]){if(d>(fx[i]+fy[j]-gp[i][j]))d=fx[i]+fy[j]-gp[i][j];}}}for(i=0;i<n;i++){if(vx[i])fx[i]-=d,vx[i]=0;if(vy[i])fy[i]+=d,vy[i]=0;}}}ans=0;for(i=0;i<n;i++){ans+=gp[m[i]][i];}return ans;}int main(){int i,j;while(1){scanf("%d",&n);if(n==0)return 0;for(i=0;i<n;i++)for(j=0;j<n;j++){scanf("%d",&gp[i][j]);}printf("%d\n",count());}return 0;}