zoukankan      html  css  js  c++  java
  • 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;
    }
    

  • 相关阅读:
    Linux内核RPC请求过程
    二分图
    Java实现 蓝桥杯 算法提高 合并石子
    Java实现 蓝桥杯 算法提高 合并石子
    Java实现 蓝桥杯 算法提高 摩尔斯电码
    Java实现 蓝桥杯 算法提高 摩尔斯电码
    Java实现 蓝桥杯 算法提高 文本加密
    Java实现 蓝桥杯 算法提高 文本加密
    Java蓝桥杯 算法提高 九宫格
    Java蓝桥杯 算法提高 九宫格
  • 原文地址:https://www.cnblogs.com/csnd/p/12062737.html
Copyright © 2011-2022 走看看