POJ2400 Supervisor, Supervisee 最小权匹配

  题目链接:http://poj.org/problem?id=2400

  话说光理解题意就搞了很久啊,说说题意吧:公司有n个管理者要招聘n个员工,所以每个管理者对每个员工进行面试,然后管理者和员工相互做出评价,每个管理者要对每个员工打分,同样每个员工要对每个管理者打分,分数越低评价越高,分数范围0,n-1。题目要求你对管理者和员工进行配对,要求所有配对的管理者和员工的分数之和最小,并且输出所有的情况。

  这个题目的难点就是要求所有的情况,我一开始想的就是枚举全排列做了,但看到数据量n<15,枚举是O(n!),如果数据恶心点,那么也会超时!想了一天,实在是没有其他的方法啊!其实n<15也已经暗示了要枚举做的啊!DFS试试,果然63ms就A了!看来以后还得把题目看得透一点!回想自己做区预赛的题目,每次也是遇到时间复杂度理论上限铁定会超时的时候,都不敢动手,但赛后发现,其实很多是可以搞的,所以经验还有待加强啊!                 PS:这题数据是反的= =。

  1 //STATUS:G++_AC_63MS_716KB
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 #include<math.h>
  6 #include<iostream>
  7 #include<string>
  8 #include<algorithm>
  9 #include<vector>
 10 #include<queue>
 11 #include<stack>
 12 using namespace std;
 13 #define LL long long
 14 #define Max(a,b) ((a)>(b)?(a):(b))
 15 #define Min(a,b) ((a)<(b)?(a):(b))
 16 #define mem(a,b) memset(a,b,sizeof(a))
 17 #define lson l,mid,rt<<1
 18 #define rson mid+1,r,rt<<1|1
 19 const int MAX=20,INF=200000000;
 20 
 21 int w[MAX][MAX],S[MAX],T[MAX],lx[MAX],ly[MAX],A[MAX],y[MAX],vis[MAX];
 22 int Tu,n,ans,anscou,slack;
 23 
 24 int match(int u)
 25 {
 26     int v,t;
 27     S[u]=1;
 28     for(v=1;v<=n;v++){
 29         t=w[u][v]-lx[u]-ly[v];
 30         if(!t){
 31             if(!T[v]){
 32                 T[v]=1;
 33                 if(!y[v] || match(y[v])){
 34                     y[v]=u;
 35                     return 1;
 36                 }
 37             }
 38         }
 39         else if(t<slack)slack=t;
 40     }
 41     return 0;
 42 }
 43 
 44 void KM()
 45 {
 46     int i,j,a;
 47     mem(ly,0);
 48     for(i=1;i<=n;i++){
 49         lx[i]=w[i][1];
 50         for(j=2;j<=n;j++)
 51             if(w[i][j]<lx[i])lx[i]=w[i][j];
 52     }
 53     for(i=1;i<=n;i++){
 54         while(1){
 55             slack=INF;
 56             mem(S,0);mem(T,0);
 57             if(match(i))break;
 58             for(j=1;j<=n;j++){
 59                 if(S[j])lx[j]+=slack;
 60                 if(T[j])ly[j]-=slack;
 61             }
 62         }
 63     }
 64 }
 65 
 66 void dfs(int cur,int s)
 67 {
 68     if(s>ans || (cur==n+1 && s!=ans))return ;
 69     int i;
 70     if(cur==n+1){
 71         printf("Best Pairing %d\n",anscou++);
 72         for(i=1;i<=n;i++)
 73             printf("Supervisor %d with Employee %d\n",i,A[i]);
 74         return ;
 75     }
 76     for(i=1;i<=n;i++){
 77         if(!vis[i]){
 78             vis[i]=1;
 79             A[cur]=i;
 80             dfs(cur+1,s+w[cur][i]);
 81             vis[i]=0;
 82         }
 83     }
 84 }
 85 
 86 int main()
 87 {
 88  //   freopen("in.txt","r",stdin);
 89     int i,j,t,k=1;
 90     scanf("%d",&Tu);
 91     while(Tu--)
 92     {
 93         mem(y,0);
 94         scanf("%d",&n);
 95         for(i=1;i<=n;i++){
 96             for(j=0;j<n;j++){
 97                 scanf("%d",&t);
 98                 w[t][i]=j;
 99             }
100         }
101         for(i=1;i<=n;i++){
102             for(j=0;j<n;j++){
103                 scanf("%d",&t);
104                 w[i][t]+=j;
105             }
106         }
107 
108         KM();
109 
110         for(ans=0,i=1;i<=n;i++)
111             ans+=w[y[i]][i];
112         printf("Data Set %d, Best average difference: %.6f\n",k++,ans*0.5/n);
113         anscou=1;
114         mem(vis,0);
115         dfs(1,0);
116         if(Tu)putchar('\n');
117     }
118     return 0;
119 }
原文地址:https://www.cnblogs.com/zhsl/p/2781379.html