题目链接:奔小康赚大钱
KM算法类似于匈牙利算法,只是多了些东西(最大权值的交换,记录)
不过这道题就已经是KM算法的入门题了
相比之下多了两个数组x_price[],y_price[]
x_price[]是记录其最大权
忘了一个重点:在进入匹配的时候每次都要对x_vis[],y_vis[]清空(memset一下)在匈利牙算法中记得要把v2_vis[]清空一下。
Sample Input
2 100 10 15 23
Sample Output
123
#include<stdio.h>
#include<string.h>
#define max(a,b) a>b?a:b
#define MAX 1<<31-1
bool x_vis[305],y_vis[305];
int price[305][305];
int y_link[305];
int x_price[305],y_price[305];
int n;
bool dfs(int x)
{
int y;
x_vis[x]=true;
for(y=1;y<=n;y++)
{
if(!y_vis[y] && x_price[x] + y_price[y] == price[x][y])
{
y_vis[y]=true;
if(y_link[y]==0 || dfs(y_link[y]))
{
y_link[y]=x;
return true;
}
}
}
return false;
}
void KM_solve()
{
memset(y_link,0,sizeof(y_link));
memset(x_price,0,sizeof(x_price));
memset(y_price,0,sizeof(y_price));
int x,i,j,temp;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
x_price[i]=max(x_price[i],price[i][j]);
for(x=1;x<=n;x++)
{
while(1)
{
memset(x_vis,false,sizeof(x_vis));
memset(y_vis,false,sizeof(y_vis));
if(dfs(x))
break;
else
{
temp=MAX;
for(i=1;i<=n;i++)
{
if(x_vis[i])
for(j=1;j<=n;j++)
if(!y_vis[j] && temp > x_price[i] + y_price[j] - price[i][j])
temp=x_price[i]+y_price[j]-price[i][j];
}
for(i=1;i<=n;i++)
{
if(x_vis[i])
x_price[i]-=temp;
if(y_vis[i])
y_price[i]+=temp;
}
}
}
}
}
int main()
{
int i,j;
while(~scanf("%d",&n))
{
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&price[i][j]);
KM_solve();
int max=0;
for(i=1;i<=n;i++)
{
max+=price[y_link[i]][i];
}
printf("%d\n",max);
}
return 0;
}