POJ 2400 Supervisor, Supervisee(KM)

題目鏈接

題意 :N个部门和N个员工,每个部门要雇佣一个工人,部门对每个工人打分,从1~N,1表示很想要,N表示特别不想要,每个工人对部门打分,从1~N。1表示很想去这个部门,N表示特别不想去这个部门,求一个匹配,使每个人的希望值最大。

思路 :KM算法。资料。用深搜构造所有能达到最大值的匹配情况。参考

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 
  5 using namespace std ;
  6 
  7 const int maxn = 110 ;
  8 int lx[maxn],ly[maxn] ;
  9 int left[maxn], n;
 10 bool S[maxn],T[maxn] ;
 11 int w[maxn][maxn] ;
 12 int slack[maxn] ;
 13 int y[maxn],cnt ;
 14 int ans;
 15 
 16 bool match(int x)
 17 {
 18     S[x] = true ;
 19     for(int j = 1 ; j <= n ; j++)
 20     {
 21         if(lx[x]+ly[j] == w[x][j] && !T[j])
 22         {
 23             T[j] = true ;
 24             if(!left[j] || match(left[j]))
 25             {
 26                 left[j] = x ;
 27                 return true ;
 28             }
 29         }
 30         else slack[j] = min(slack[j],w[x][j]-lx[x]-ly[j]) ;
 31     }
 32     return false ;
 33 }
 34 
 35 void KM()
 36 {
 37     for(int i = 1 ; i <= n ; i++)
 38     {
 39         left[i] = ly[i] = 0 ;
 40         lx[i] = 9999999;
 41         for(int j = 1 ; j <= n ; j++)
 42             lx[i] = min(lx[i],w[i][j]) ;
 43     }
 44     for(int x = 1 ; x <= n ; x++)
 45     {
 46         for(int i = 1 ; i <= n ; i++)
 47             slack[i] = 9999999 ;
 48         while(1)
 49         {
 50             memset(S,false,sizeof(S)) ;
 51             memset(T,false,sizeof(T)) ;
 52             if(match(x)) break ;
 53             int tmp = 9999999 ;
 54             for(int i = 1 ; i <= n ; i++)
 55                 if(!T[i])
 56                     tmp = min(tmp,slack[i]) ;
 57             if(tmp == 9999999)return ;
 58             for(int i = 1 ; i <= n ; i++)
 59             {
 60                 if(S[i]) lx[i] += tmp ;
 61                 if(T[i]) ly[i] -= tmp ;
 62             }
 63         }
 64     }
 65 }
 66 
 67 void dfs(int t,int sum)
 68 {
 69     if(sum > ans) return ;
 70     if(t > n)
 71     {
 72         if(sum != ans) return ;
 73         printf("Best Pairing %d
",++cnt) ;
 74         for(int j = 1 ; j <= n ; j++)
 75             printf("Supervisor %d with Employee %d
",j,y[j]) ;
 76         return  ;
 77     }
 78     for(int i = 1 ; i <= n ; i++)
 79     {
 80         if(!T[i])
 81         {
 82             y[t] = i ;
 83             T[i] = true ;
 84             dfs(t+1,sum+w[t][i]) ;
 85             T[i] = false ;
 86         }
 87     }
 88     return ;
 89 }
 90 int main()
 91 {
 92     int t,x ;
 93     scanf("%d", &t) ;
 94     for(int k = 1 ; k <= t  ; k++)
 95     {
 96         for(int i = 1 ; i <= n ; i++)
 97             for(int j = 1 ; j <= n ; j++)
 98                 w[i][j] = 0 ;
 99         scanf("%d",&n) ;
100         for(int i = 1 ; i <= n ; i++)
101             for(int j = 0 ; j < n ; j++)
102             {
103                 scanf("%d",&x) ;
104                 w[x][i] += j ;
105             }
106         for(int i = 1 ; i <= n ; i++)
107             for(int j = 0 ; j < n ; j++)
108             {
109                 scanf("%d",&x) ;
110                 w[i][x] += j ;
111             }
112         KM() ;
113         ans = 0 ;
114         cnt = 0 ;
115         for(int i = 1 ; i <= n  ; i++)
116             if(left[i])
117                 ans += w[left[i]][i] ;
118         printf("Data Set %d, Best average difference: %.6f
",k,ans/(2.0*n)) ;
119         memset(T,false,sizeof(T)) ;
120         dfs(1,0) ;
121         printf("
") ;
122     }
123     return 0 ;
124 }
View Code
原文地址:https://www.cnblogs.com/luyingfeng/p/3751596.html