pku 2400
2011-07-19 21:03
267 查看
题意:求最小权匹配的所有匹配方案
分析:用km()算法求得最小匹配后,对于所有的 lx[i] + ly[[j] = g[i][j] 的 i ,j 建边 i---->j。然后求新建图的所有完美匹配(dfs即可)
代码:
分析:用km()算法求得最小匹配后,对于所有的 lx[i] + ly[[j] = g[i][j] 的 i ,j 建边 i---->j。然后求新建图的所有完美匹配(dfs即可)
代码:
#include<stdio.h> #include<string.h> #define N 20 #define inf 1000000000 int lx ,ly ,vx ,vy ,x ,y ; int g ,slack ; char map ; int a ,b ; int m,n,num; int search(int u) { int v;vx[u]=1; for(v=1;v<=n;v++) { if(vy[v]) continue; if(lx[u]+ly[v]==g[u][v]) { vy[v]=1; if(y[v]==-1||search(y[v])) { x[u]=v;y[v]=u; return 1; } } else if(lx[u]+ly[v]-g[u][v]<slack[v]) slack[v]=lx[u]+ly[v]-g[u][v]; } return 0; } int KM() { int i,j,min,ans; memset(ly,0,sizeof(ly)); memset(x,-1,sizeof(x)); memset(y,-1,sizeof(y)); for(i=1;i<=m;i++) { for(lx[i]=-inf,j=1;j<=n;j++) if(lx[i]<g[i][j]) lx[i]=g[i][j]; } for(i=1;i<=m;i++) { for(j=1;j<=n;j++) slack[j]=inf; while(x[i]==-1) { memset(vx,0,sizeof(vx)); memset(vy,0,sizeof(vy)); if(search(i)) break; //更新顶标 for(min=inf,j=1;j<=n;j++) if(!vy[j]&&slack[j]<min) min=slack[j]; for(j=1;j<=m;j++) if(vx[j]) lx[j]-=min; for(j=1;j<=n;j++) if(vy[j]) ly[j]+=min; else slack[j]-=min; } } for(ans=0,i=1;i<=n;i++) { if(y[i]==-1) return -1;//无匹配 if(g[y[i]][i]==-inf) return -1; ans+=g[y[i]][i]; } return ans; } void dfs(int i) { int j; if(i==n+1) { printf("Best Pairing %d\n",num++); for(j=1;j<=n;j++) printf("Supervisor %d with Employee %d\n",j,x[j]); return ; } for(j=1;j<=n;j++) if(map[i][j]&&!vy[j]) { vy[j]=1;x[i]=j; dfs(i+1); vy[j]=0; } } int main() { int t,i,j,k,cas=1; scanf("%d",&t); while(t--) { scanf("%d",&n); m=n; for(i=1;i<=n;i++) for(j=1;j<=n;j++) { scanf("%d",&k); b[i][k]=j-1; } for(i=1;i<=n;i++) for(j=0;j<n;j++) { scanf("%d",&k); a[i][k]=j; } for(i=1;i<=n;i++) for(j=1;j<=n;j++) g[i][j]=-(a[i][j]+b[j][i]); int ans=-1*KM(); printf("Data Set %d, Best average difference: %lf\n",cas++,(ans*1.0)/(2*n*1.0)); memset(map,0,sizeof(map)); memset(vy,0,sizeof(vy)); for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(lx[i]+ly[j]==g[i][j]) map[i][j]=1; num=1; dfs(1); if(t!=0)printf("\n"); } return 0; }
相关文章推荐
- pku 2400 Supervisor, Supervisee KM求最小权匹配+DFS回溯解集
- pku 1517 u Calculate e
- pku3244(公式变换,推理)
- pku1106Transmitters
- PKU 1504 Adding Reversed Numbers
- pku 2337 Catenyms
- pku 1442 Black Box(优先队列)
- pku 3259 Wormholes(SPFA判负环)
- pku 3749 破译密码
- pku 2629 Common permutation
- pku 1028 Web Navigation
- pku 1915 Knight Moves
- pku1088滑雪 记忆搜索
- PKU 1024 Web Navigation 解法及教训总结
- pku 3159 Candies
- pku 1565 Skew Binary
- pku 3621
- PKU1703 find them catch them
- PKU 1091 跳蚤 数论 容斥原理
- pku 3017 单调队列优化DP