hdu 5045 费用流

题意:
     网选赛的一个题目,当时各种超时各种wa,哎! 题意是有n个人m道题,每个人对每道题都有一个ac率,每相邻的n到题目必须n个人每人一道,顺序无所谓,上下的m%n道只要不出现一个人做两道就行,最后要求输出最大的ac率。


思路:

     第一眼就感觉是网络流,然后建了一个很复杂的图,结果各种超时,当时吧这个题目想的复杂了,队友后来用dp过了这个题目,感觉有点失落啊,回去了第二天早上又敲了一边费用流,ac了,哎! 感觉没那么难受了,要是没看出来是网络流做不出来也就算了,看出来了,没敲出来,感觉耻辱啊,其实这个题目并不难,我们直接跑m/k+m%k次网络流就行了,具体看代码,一开始我的建图是跑一遍,然后给每个n个题目虚拟出n个人来,如果有余数在虚拟出n个人来,结果各种wa到现在也没找到原因,m/k+m%k次的细节具体看代码。




#include<stdio.h>
#include<string.h>
#include<queue>

#define N_node 50
#define N_edge 500
#define INF 100000000

using namespace std;

typedef struct
{
   int from ,to ,next ,flow;
   double cost;
}STAR;

STAR E[N_edge];
int    list[N_node] ,tot;
int    mer[N_edge];
double s_x[N_node];
double num[15][1100];

void add(int a ,int b ,double c ,int d)
{
     
     E[++tot].from = a;
     E[tot].to = b;
     E[tot].cost = c;
     E[tot].flow = d;
     E[tot].next = list[a];
     list[a] = tot;
     
     E[++tot].from = b;
     E[tot].to = a;
     E[tot].cost = -c;
     E[tot].flow = 0;
     E[tot].next = list[b];
     list[b] = tot;
}

bool spfa(int s ,int t ,int n)
{
     int mark[N_node] = {0};
     for(int i = 0 ;i <= n ;i ++)
     s_x[i] = -INF;
     mark[s] = 1,s_x[s] = 0;
     queue<int>q;
     q.push(s);
     memset(mer ,255 ,sizeof(mer));
     while(!q.empty())
     {
        int xin ,tou;
        tou = q.front();
        q.pop();
        mark[tou] = 0;
        for(int k = list[tou] ;k ;k = E[k].next)
        {
           xin = E[k].to;
           if(s_x[xin] < s_x[tou] + E[k].cost && E[k].flow)
           {
              s_x[xin] = s_x[tou] + E[k].cost;
              mer[xin] = k;
              if(!mark[xin])
              {
                 mark[xin] = 1;
                 q.push(xin);
              }
           }
        }
     }
     return mer[t] != -1;
}

double M_C_Flow(int s ,int t ,int n)
{
   int maxflow = 0 ,minflow;
   double maxcost = 0;
   while(spfa(s ,t ,n))
   {
      minflow = INF;
      for(int i = mer[t] ;i + 1 ;i = mer[E[i].from])
      if(minflow > E[i].flow) minflow = E[i].flow;
      for(int i = mer[t] ;i + 1 ;i = mer[E[i].from])
      {
          E[i].flow -= minflow;
          E[i^1].flow += minflow;
          maxcost += minflow * E[i].cost;
      }
      maxflow += minflow;
   }
   return maxcost;
}

int main ()
{
    int n ,m ,i ,j ,t ,cas = 1;
    scanf("%d" ,&t);
    while(t--)
    {
        scanf("%d %d" ,&n ,&m);
        for(i = 1 ;i <= n ;i ++)
        for(j = 1 ;j <= m ;j ++)
        scanf("%lf" ,&num[i][j]);
        double Ans = 0;
        for(i = 1 ;i <= m ;i ++)
        {
           if(i % n == 0)
           {
              memset(list ,0 ,sizeof(list)) ,tot = 1; 
              for(int ii = 1 ;ii <= n ;ii ++) add(0 ,ii ,0 ,1);
              for(int ii = 1 ;ii <= n ;ii ++)
              for(int jj = 1 ;jj <= n ;jj ++)
              add(ii ,n + jj ,num[ii][i-n+jj] ,1);
              for(int ii = 1 ;ii <= n ;ii ++) add(ii + n ,n + n + 1 ,0 ,1);
              Ans += M_C_Flow(0 ,n + n + 1 ,n + n + 1);
           }  
        }
        if(m % n)
        {
              memset(list ,0 ,sizeof(list)) ,tot = 1; 
              for(int ii = 1 ;ii <= n ;ii ++) add(0 ,ii ,0 ,1);
              for(int ii = 1 ;ii <= n ;ii ++)
              for(int jj = 1 ;jj <= m % n ;jj ++)
              add(ii ,n + jj ,num[ii][m-(m%n)+jj] ,1);
              for(int ii = 1 ;ii <= n ;ii ++) add(ii + n ,n + n + 1 ,0 ,1);
              Ans += M_C_Flow(0 ,n + n + 1 ,n + n + 1);
        }
        
        
       
        printf("Case #%d: %.5lf
" ,cas ++ ,Ans);
     }
     return 0;
}

原文地址:https://www.cnblogs.com/csnd/p/12062737.html