hdu2426——Interesting Housing Problem

最大权匹配算法解析
本文深入探讨了最大权匹配算法的实现细节,并提供了一个具体的C++实现案例。通过对算法逐步剖析,帮助读者理解如何通过调整边的权重来寻找最优匹配方案。

过得稀里糊涂,对最大权值的匹配还是不甚理解,明天继续!!!

终于对此算法有点理解了!不过,下面这个发现有些BUG,另贴一个!

#include<stdio.h> #include<string.h> #define INF 0xfffffff int g[502][502],s,r,e; int lx[502],ly[502],my[502],stack[502]; bool vx[502],vy[502]; int find(int v) { int i,temp; vx[v]=true; for(i=0;i<r;i++) { if(!vy[i]) { temp=lx[v]+ly[i]-g[v][i]; if(temp==0) { vy[i]=true; if(my[i]==-1||find(my[i])) { my[i]=v; return true; } } else if(temp<stack[i]) stack[i]=temp; } } return false; } void KM() { int i,j,min; for(i=0;i<s;i++) { lx[i]=0; for(j=0;j<r;j++) if(lx[i]<g[i][j]) lx[i]=g[i][j]; } for(j=0;j<r;j++) ly[j]=0; memset(my,-1,sizeof(my)); for(i=0;i<s;i++) { for(j=0;j<r;j++) stack[j]=INF; while(1) { memset(vx,false,sizeof(vx)); memset(vy,false,sizeof(vy)); min=INF; if(find(i)) break; for(j=0;j<r;j++) { if(!vy[j]&&stack[j]<min) min=stack[j]; } for(j=0;j<s;j++) if(vx[j]) lx[j]-=min; for(j=0;j<r;j++) { if(vy[j]) ly[j]+=min; else stack[j]-=min; } } } } int main() { int i,j,CASE=0,a,b,c,t; while(scanf("%d%d%d",&s,&r,&e)!=EOF) { if(e==0) printf("Case %d: %d\n",++CASE,-1); else { for(i=0;i<s;i++) for(j=0;j<r;j++) g[i][j]=-INF; while(e--) { scanf("%d%d%d",&a,&b,&c); if(c>=0) g[a][b]=c; } KM(); int ans=0,cnt=0; for(i=0;i<r;i++) { t=my[i]; if(t>=0&&g[t][i]!=-INF) { cnt++; ans+=g[t][i]; } } if(cnt<s) ans=-1; printf("Case %d: %d\n",++CASE,ans); } } return 0; }

转:

#include<iostream> using namespace std; #define Max(a,b) (a)>(b) ? (a) : (b) #define Min(a,b) (a)<(b) ? (a) : (b) const int INF=0x7f7f7f7f; const int MAXN=501; int n,m,e,res; int w[MAXN][MAXN]; int mat[MAXN],slack[MAXN]; int lx[MAXN],ly[MAXN],vx[MAXN],vy[MAXN]; bool dfs(int u) { int v,t; vx[u]=1; for(v=0;v<m;++v) { if(!vy[v]) { t=lx[u]+ly[v]-w[u][v]; if(t==0) { vy[v]=1; if(mat[v]==-1||dfs(mat[v])) { mat[v]=u;return true; } } else slack[v]=Min(slack[v],t); } } return false; } bool km() { memset(mat,-1,sizeof(mat)); memset(ly,0,m*sizeof(ly[0])); for(int i=0;i<n;++i) { lx[i]=-INF; for(int j=0;j<m;++j) lx[i]=Max(lx[i],w[i][j]); if(lx[i]==-INF) return false; } for(int i=0;i<n;++i) { memset(slack,127,m*sizeof(slack[0])); while(true) { memset(vx,0,n*sizeof(vx[0])); memset(vy,0,m*sizeof(vy[0])); if(dfs(i)) break; int d=INF; for(int j=0;j<m;++j) if(!vy[j]) d=Min(slack[j],d); for(int j=0;j<n;++j) if(vx[j]) lx[j]-=d; for(int j=0;j<m;++j) if(vy[j]) ly[j]+=d; } } int cnt=res=0; for(int i=0;i<m;++i) if(mat[i]!=-1&&w[mat[i]][i]!=-INF) res+=w[mat[i]][i],cnt++; if(cnt==n) return true; return false; } int main() { bool flag; int s,r,v,len,tmp,num=0; while(scanf("%d%d%d",&n,&m,&e)!=EOF) { flag=true; if(n>m) { flag=false; for(int i=0;i<e;++i) scanf("%d%d%d",&s,&r,&v); } else { for(int i=0;i<n;++i) for(int j=0;j<m;++j) w[i][j]=-INF; for(int i=0;i<e;++i) { scanf("%d%d%d",&s,&r,&v); if(v>=0) w[s][r]=v; } flag=km(); } printf("Case %d: ",++num); if(!flag) printf("-1\n"); else printf("%d\n",res); } return 0; }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值