hdu2255

来源:互联网 发布:石油计量表软件 编辑:程序博客网 时间:2024/05/19 17:10

KM水题。KM是求完备匹配下的最优匹配。直接贴代码:

608K+604MS

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 310#define Inf 1000010int match[Max][Max];bool visy[Max];bool visx[Max];int pre[Max];int slack[Max];int lx[Max];int ly[Max];int n;bool find(int x){visx[x]=true;for(int i=1;i<=n;i++){if(visy[i])continue;int t=lx[x]+ly[i]-match[x][i];if(t==0){visy[i]=true;if(pre[i]==-1 || find(pre[i])){pre[i]=x;return true;}}else if(t<slack[i])slack[i]=t;}return false;}int Km(){memset(ly,0,sizeof(ly));memset(pre,-1,sizeof(pre));int i,j;for(i=1;i<=n;i++)for(j=1,lx[i]=-Inf;j<=n;j++)if(lx[i]<match[i][j])lx[i]=match[i][j];for(i=1;i<=n;i++){for(j=1;j<=n;j++)slack[j]=Inf;while(true){memset(visx,0,sizeof(visx));memset(visy,0,sizeof(visy));if(find(i))break;int d=Inf;for(j=1;j<=n;j++)if(!visy[j] && slack[j]<d)d=slack[j];for(j=1;j<=n;j++)if(visx[j])lx[j]-=d;for(j=1;j<=n;j++)if(visy[j])ly[j]+=d;    elseslack[j]-=d;}}int ans=0;for(i=1;i<=n;i++)if(pre[i]!=-1)ans+=match[pre[i]][i];return ans;}int main(){while(scanf("%d",&n)!=EOF){for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&match[i][j]);printf("%d\n",Km());}return 0;}

若要求最小费用则代码如下:

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 310#define Inf 1000010int match[Max][Max];bool visy[Max];bool visx[Max];int pre[Max];int slack[Max];int lx[Max];int ly[Max];int n;bool find(int x){visx[x]=true;for(int i=1;i<=n;i++){if(visy[i])continue;int t=match[x][i]-(lx[x]+ly[i]);if(t==0){visy[i]=true;if(pre[i]==-1 || find(pre[i])){pre[i]=x;return true;}}else if(t<slack[i])slack[i]=t;}return false;}int Km(){memset(ly,0,sizeof(ly));memset(pre,-1,sizeof(pre));int i,j;for(i=1;i<=n;i++)for(j=1,lx[i]=Inf;j<=n;j++)if(lx[i]>match[i][j])lx[i]=match[i][j];for(i=1;i<=n;i++){for(j=1;j<=n;j++)slack[j]=Inf;while(true){memset(visx,0,sizeof(visx));memset(visy,0,sizeof(visy));if(find(i))break;int d=Inf;for(j=1;j<=n;j++)if(!visy[j] && slack[j]<d)d=slack[j];for(j=1;j<=n;j++)if(visx[j])lx[j]+=d;for(j=1;j<=n;j++)if(visy[j])ly[j]-=d;    elseslack[j]-=d;}}int ans=0;for(i=1;i<=n;i++)if(pre[i]!=-1)ans+=match[pre[i]][i];return ans;}int main(){while(scanf("%d",&n)!=EOF){for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&match[i][j]);printf("%d\n",Km());}return 0;}


 

0 0
原创粉丝点击