POJ 2400 Supervisor, Supervisee(KM+DFS找相同最佳匹配)
专门去找了图论的题目,最近就在这上面下功夫了,虽然学长把DP讲了,不过似乎没那么多的时间去攻克,一个个来吧。做事不急才好啊!今天做这题挺有成就感的,POJ上A掉得才405个,感觉不错;
这题初看感觉很复杂,各种输出,其实主要思想可以转换成找最小匹配,一边是员工,一边是老板(可以这么理解),好老板喜欢好员工,好员工喜欢好老板,所以有了相互的评价,就是题目给的,那就用KM找最小匹配!找最小匹配的话就把相互的评价带成负值,最后算总值再加个负号就行了!
里面的“Best average difference” 其实就是员工的总评价除以2*n(人数,因为是双方,你懂得),一次KM得到的值作为对比,进行一次DFS找边,替换一条rank中已经找到的边,看是否能找到答案相同的匹配方案,然后输出就可;
#include <iostream> #include <stdio.h> using namespace std; #define NN 20 int map[NN][NN]; int n,lack; bool visx[NN],visy[NN]; int dx[NN],dy[NN]; int rank[NN]; int sum; double ans; bool flag[NN]; bool DFS(int v) { visx[v]=true;; int i; for(i=1;i<=n;i++) { if(visy[i]) continue; int t=dx[v]+dy[i]-map[v][i]; if(!t) { visy[i]=true; if(rank[i]==-1||DFS(rank[i])) { rank[i]=v; return true; } } else if(lack>t) lack=t; } return false; } double KM() { memset(dx,0,sizeof(dx)); memset(dy,0,sizeof(dy)); memset(rank,-1,sizeof(rank)); int i,j; for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(dx[i]<map[i][j]) dx[i]=map[i][j]; for(i=1;i<=n;i++) { while(true) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); lack=0xfffff; if(DFS(i)) break; for(j=1;j<=n;j++) { if(visx[j]) dx[j]-=lack; if(visy[j]) dy[j]+=lack; } } } ans=0; for(i=1;i<=n;i++) ans+=-map[rank[i]][i];//值变为正的 return 1.0*ans/(2*n);//那个平均值求法在这 }//以上都是模板 没什么变化 void KM_DFS(int left,int dx) { int i,j; if(left<0) return ; if(left==0) { if(dx==n+1) //满足条件输出 { printf("Best Pairing %d\n",sum++); for(i=1;i<=n;i++) { printf("Supervisor %d with Employee %d\n",i,rank[i]); } } return ; } for(j=1;j<=n;j++) //替换一个已找到边 if(!flag[j]) { flag[j]=true; rank[dx]=j; KM_DFS(left+map[dx][j],dx+1); flag[j]=false; } } int main() { int t,m,i,j; scanf("%d",&t); int k=1; while(t--) { memset(map,0,sizeof(map)); scanf("%d",&n); for(i=1;i<=n;i++) for(j=1;j<=n;j++) { scanf("%d",&m); map[m][i]-=j; } for(i=1;i<=n;i++) for(j=1;j<=n;j++) { scanf("%d",&m); map[i][m]-=j; } double mu=KM(); int p=2; printf("Data Set %d, Best average difference: %.6lf\n",k++,mu-1); sum=1; memset(flag,false,sizeof(flag)); KM_DFS(ans,1); printf("\n"); } return 0; }