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;
}

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