POJ 2686 The Windy's(KM算法)

题目链接

拆点+KM,建图思路看的题解。。。

看懂的题意后,想了好一会。知道这题是KM,但是不会建图,无奈啊。

建图很巧妙,假如同一个机器上加工了k件物品,那么实际花费时间k*a1+(k-1)*a2+(k-3)*a3....

其实对这个拆点,也不是很懂。

这样把m个机器拆成n个点,表示是第几个加工的。套上模版,这题是求最小权,取一下相反数就行了。

拆成两个集合一个存n个物品,另一个存第i个机器上第j个加工。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <string>
  4 #include <cstdio>
  5 #include <algorithm>
  6 using namespace std;
  7 #define N 2552
  8 #define INF 0x7fffffff
  9 int mat[N][N];
 10 int inx[N],iny[N];
 11 int lx[N],ly[N];
 12 int match[N];
 13 int n,m;
 14 int inp[N][N];
 15 int dfs(int u)
 16 {
 17     inx[u] = 1;
 18     int i;
 19     for(i = 1; i <= m*n; i ++)
 20     {
 21         if(!iny[i]&&lx[u]+ly[i] == mat[u][i])
 22         {
 23             iny[i] = 1;
 24             if(match[i] == -1||dfs(match[i]))
 25             {
 26                 match[i] = u;
 27                 return 1;
 28             }
 29         }
 30     }
 31     return 0;
 32 }
 33 void KM()
 34 {
 35     int i,j,k,temp;
 36     for(i = 1;i < N;i ++)
 37     {
 38         lx[i] = -INF;
 39         ly[i] = -INF;
 40     }
 41     for(i = 1; i <= n; i ++)
 42     {
 43         for(j = 1; j <= m*n; j ++)
 44             lx[i] = max(lx[i],mat[i][j]);
 45     }
 46     for(i = 1; i <= n; i ++)
 47     {
 48         for(;;)
 49         {
 50             memset(inx,0,sizeof(inx));
 51             memset(iny,0,sizeof(iny));
 52             if(dfs(i))
 53                 break;
 54             else
 55             {
 56                 temp = INF;
 57                 for(j = 1; j <= n; j ++)
 58                 {
 59                     if(inx[j])
 60                     {
 61                         for(k = 1; k <= m*n; k ++)
 62                         {
 63                             if(!iny[k]&&temp > lx[j]+ly[k]-mat[j][k])
 64                             temp = lx[j]+ly[k]-mat[j][k];
 65                         }
 66                     }
 67                 }
 68                 for(j = 1;j <= n;j ++)
 69                 {
 70                     if(inx[j])
 71                     lx[j] -= temp;
 72                 }
 73                 for(j = 1;j <= m*n;j ++)
 74                 {
 75                     if(iny[j])
 76                     ly[j] += temp;
 77                 }
 78             }
 79         }
 80     }
 81 }
 82 int main()
 83 {
 84      int i,j,k,cas;
 85      scanf("%d",&cas);
 86      while(cas--)
 87      {
 88          scanf("%d%d",&n,&m);
 89          memset(match,-1,sizeof(match));
 90          for(i = 1;i <= n;i ++)
 91          {
 92              for(j = 1;j <= m;j ++)
 93              {
 94                  scanf("%d",&inp[i][j]);
 95              }
 96          }
 97          for(i = 1;i <= n;i ++)
 98          {
 99              for(j = 1;j <= m;j ++)
100              {
101                  for(k = 1;k <= n;k ++)
102                  {
103                      mat[i][(j-1)*n+k] = -((n-k+1)*inp[i][j]);
104                  }
105              }
106          }
107          KM();
108          int ans = 0;
109          for(i = 1;i <= n*m;i ++)
110          {
111              if(match[i] != -1)
112              ans += mat[match[i]][i];
113          }
114          printf("%.6lf\n",-ans*1.0/n);
115      }
116      return 0;
117  }

 

posted @ 2013-04-17 21:15  Naix_x  阅读(187)  评论(0编辑  收藏  举报