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  }

 

你可能感兴趣的:(poj)