zoukankan      html  css  js  c++  java
  • hdu4862 费用流(不错)

    题意:
          给你一个矩阵,你最多可以选择k条路线,k条路线的起点随意,每次行走的距离随意,但是只能往右或者下走,走过的点不能再走,而且每一步如果a->b,如果a和b的权值s相等那么就可以获得s这么多能量,每一步花费的能量是|x1 - x2| + |y1 - y2| - 1,最后问你吧所有点都遍历后获得的最大能量是多少。


    思路:
          每个点只能走一次,最多可以选择k条路径,要求全走完的最大,显然是费用流,我写的是最大费用最大流,(最小费用最大流也行,就是正负的问题)下面说建边。
      (1) 首先虚拟出来三个点,源点s,终点e,超级远点ss。
     *(2) 拆点 a -> a'  流量1,费用INF //每个点只能访问一次,INF是为了让所有的点都访 问到,这个是关键,如果     是最消费用流的话可以使 -INF 
      (3) ss -> s 费用0流量k  //限制路径条数
      (4) s -> a  费用0流量1  // 每一个点都可以当路径起点
      (5) a' -> b 费用 可获得价值-花费 流量是1 // 每个点让他右和下的所有点建边
      (6) a' -> e 费用0,流量1 //每个点都可以做路径终点
     *(7) s -> e  费用0,流量INF // 题目说k可以不全用,排除强制用k条导致的错误

          这样就行了,还有就是说明下这个题目如果可以覆盖的话根本不存在负的答案,题目的那句话是误导人的,如果出现负的,那么就直接是无解的,因为ans = mclow - n * m * INF,INF很大,只要有一个格子没被覆盖过,那么abs就直接是负值了。



    #include<stdio.h>
    #include<string.h>
    #include<queue>
    
    #define N_node 220
    #define N_edge 33000
    #define INF 10000000
    
    using namespace std;
    
    typedef struct
    {
       int from ,to ,next ,cost ,flow;
    }STAR;
    
    STAR E[N_edge];
    int list[N_node] ,tot;
    int s_x[N_node];
    int mer[N_edge];
    
    void add(int a ,int b ,int 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)
    {
       for(int i = 0 ;i <= n ;i ++)
       s_x[i] = -1000000000;
       int mark[N_node] = {0};
       s_x[s] = 0 ,mark[s] = 1;
       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(E[k].flow && s_x[xin] < s_x[tou] + E[k].cost)
             {
                mer[xin] = k;
                s_x[xin] = s_x[tou] + E[k].cost;
                if(!mark[xin]) 
                {
                   mark[xin] = 1;
                   q.push(xin);
                }
             }
          }
       }
       return mer[t] != -1;
    }
    
    int M_C_Flow(int s ,int t ,int n ,int nn ,int mm)
    {
       int maxcost = 0 ,minflow ,maxflow = 0;
       while(spfa(s ,t ,n))
       {
          maxflow = 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 += E[i].cost * minflow;
          }
          maxflow += minflow;
       }
       return maxcost;
    }
    
    int abss(int x)
    {
       return x < 0 ? -x : x;
    }
    
    int main ()
    {
       int map[15][15];
       int n ,m ,k ,i ,cas = 1 ,t ,j;
       scanf("%d" ,&t);
       while(t--)
       {
          scanf("%d %d %d" ,&n ,&m ,&k);
          char tmp[15];
          for(i = 1 ;i <= n ;i ++)
          {
             scanf("%s" ,tmp);
             for(j = 1 ;j <= m ;j ++)
             map[i][j] = tmp[j-1] - '0';
          }
          memset(list ,0 ,sizeof(list)) ,tot = 1;
          
          for(i = 1 ;i <= n ;i ++)
          for(j = 1 ;j <= m ;j ++)
          {
             int now = (i - 1) * m + j;
             add(now ,now + n * m ,INF ,1);
          }
          
          int s = 0 ,ss = n * m * 2 + 1 ,e = n * m * 2 + 2;
          add(s ,ss ,0 ,k);
          for(i = 1 ;i <= n ;i ++)
          for(j = 1 ;j <= m ;j ++)
          {
             int now = (i - 1) * m + j;
             add(ss ,now ,0 ,1);
             add(now + n * m ,e ,0 ,1);
             for(k = i + 1 ;k <= n ;k ++)
             {
                int to = (k - 1) * m + j;
                int dis = abss(i - k) - 1;
                if(map[i][j] == map[k][j])
                add(now + n * m ,to ,map[i][j] - dis,1);
                else add(now + n * m ,to ,0 - dis ,1);
             }
             
             for(k = j + 1 ;k <= m ;k ++)
             {
                int to = (i - 1) * m + k;
                int dis = abss(j - k) - 1;
                if(map[i][j] == map[i][k])
                add(now + n * m ,to ,map[i][j] - dis,1);
                else add(now + n * m ,to ,0 - dis ,1);
             }
          }
          add(ss ,e ,0 ,INF);
          int ans = M_C_Flow(s ,e ,e ,n ,m) - n * m * INF;
          if(ans < 0) ans = -1;
          printf("Case %d : " ,cas ++);
          printf("%d
    " ,ans);
       }
       return 0;
    }
    

  • 相关阅读:
    疫情在家没事做推荐个学习的目录:怎么从一名码农成为架构师的必看知识点:目录大全(不定期更新)
    教你使用 Swoole-Tracker 秒级定位 PHP 卡死问题
    怎样深入学习php,成为php高手!?
    PHP实现简单RPC
    PHP工作岗位要求
    关于PHP在企业级开发领域的访谈
    未知及待办清单
    siege报告学习
    session&token based auth登录方式描述
    学习JWT
  • 原文地址:https://www.cnblogs.com/csnd/p/12062935.html
Copyright © 2011-2022 走看看