Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 108 Accepted Submission(s): 37
2 100 10 15 23
123
最大权匹配,模板题一道
#include<stdio.h>
#include<string.h>
int g[305][305];//邻接矩阵
int lx[305],ly[305];//顶点标号
bool sx[305],sy[305];//是否已经搜索过
int link[305],n;
int min(int a,int b)
{
if(a<b) return a;
return b;
}
bool path(int k)//从x[k]寻找增广路
{
sx[k]=true;
for(int i=0; i<n; i++)
{
if(!sy[i]&&(lx[k]+ly[i]==g[k][i]))
{
sy[i]=1;
if(link[i]==-1||path(link[i]))
{
link[i]=k;
return true;
}
}
}
return false;
}
int BestMatch()//求解最小权匹配
{
int d,sum;
memset(ly,0,sizeof(ly));
memset(link,-1,sizeof(link));
for(int i=0; i<n; i++)
{
lx[i]=-1; //x中顶点i的编号为与i关联的Y中边的最大权重
for(int j=0; j<n; j++) if(lx[i]<g[i][j]) lx[i]=g[i][j];
}
for(int k=0; k<n; k++)
{
while(1)
{
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
if(path(k)) break;//匹配成功
d=1<<25-1;
for(int i=0; i<n; i++)
if(sx[i])
for(int j=0; j<n; j++)
if(!sy[j]) d=min(d,lx[i]+ly[j]-g[i][j]);
for(int i=0; i<n; i++)
{
if(sx[i]) lx[i]-=d;
if(sy[i]) ly[i]+=d;
}
}
}
sum=0;
for(int i=0; i<n; i++) sum+=g[link[i]][i];
return sum;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
int x;
scanf("%d",&x);
g[i][j]=x;
}
printf("%d/n",BestMatch());
}
return 0;
}