• poj3422 Kaka's Matrix Travels(最小费用最大流问题)


      1 /*
      2 poj3422 Kaka's Matrix Travels 
      3 不知道 k次 dp做为什么不对???
      4 看了大牛的代码,才知道还可以这样做! 
      5 开始没有理解将a 和 a‘ 之间建立怎样的两条边,导致程序一直陷入死循环,真心花了好长时间,快崩溃了。无语..... 
      6 题意:有个方阵,每个格子里都有一个非负数,从左上角走到右下角,每次走一步,只能往右或往下走,经过的数字拿走 
      7 每次都找可以拿到数字和最大的路径走,走k次,求最大和 
      8  
      9 这是 最大费用最大流 问题  每次spfa都找的是一条和最大的路径 s--到左上角的边流量是K限制增广次数 
     10  
     11 求最大费用最大流只需要把费用换成相反数,用最小费用最大流求解即可 
     12  
     13  
     14 构图过程:
     15 每个点拆分成两个  a   a'   之间建两条边(当然还要建退边),分别是   (费用为该点相反数,流量为1) (费用为0,流量为k-1) 
     16 路过这点时,可以通过前边那条边拿到数字, 
     17 以后再从这儿过,就没有数字可拿了,走的就是第二条边 
     18  
     19 然后是 没点向 右和下 建一条边  费用0,流量k 
     20 */
     21 #include<iostream>
     22 #include<queue>
     23 #include<cstring>
     24 #include<cstdio> 
     25 #define N 50000
     26 #define M 5005
     27 #define Max 0x3f3f3f3f
     28 using namespace std;
     29 class EDGE
     30 {
     31 public:
     32    int u, v, c, f;
     33    int next;
     34 };
     35 queue<int>q; 
     36 EDGE edge[N];
     37 int cap[55][55], n, k;
     38 int pre[N], first[N];
     39 int dist[M], vis[M];
     40 int edgeN;
     41 int s, t;
     42 int maxFlow;
     43 
     44 int spfa()
     45 {
     46     memset(dist, 0x3f, sizeof(dist));
     47     memset(vis, 0, sizeof(vis));
     48     memset(pre, -1, sizeof(pre));
     49     dist[s]=0;
     50     q.push(s);
     51     vis[s]=1;
     52     while(!q.empty())
     53     {
     54         int u=q.front();
     55         q.pop();
     56         vis[u]=0;
     57         for(int e=first[u]; e!=-1; e=edge[e].next)
     58         {
     59           int v=edge[e].v; 
     60           if(dist[v]>dist[u] + edge[e].c && edge[e].f>0)
     61            {
     62                dist[v]=dist[u] + edge[e].c;
     63                pre[v]=e;
     64                if(!vis[v])
     65                {
     66                      vis[v]=1;
     67                      q.push(v);
     68            }
     69        }
     70     } 
     71      }
     72      if(dist[t]==Max)
     73        return 0;
     74      return 1;
     75 }
     76 
     77 void updateFlow()
     78 {
     79    int minF=Max;
     80    for(int e=pre[t]; e!=-1; e=pre[edge[e].u])
     81      if(minF>edge[e].f)
     82         minF=edge[e].f;
     83    for(int e=pre[t]; e!=-1; e=pre[edge[e].u])
     84    {
     85       edge[e].f-=minF;
     86       edge[e^1].f+=minF;
     87       maxFlow+=minF*edge[e].c;
     88    }
     89 }
     90 
     91 void adde(int u, int v, int c, int f)
     92 {
     93     edge[edgeN].u=u; edge[edgeN].v=v;
     94     edge[edgeN].c=c; edge[edgeN].f=f;
     95     edge[edgeN].next=first[u]; first[u]=edgeN++;
     96     
     97     edge[edgeN].u=v; edge[edgeN].v=u;
     98     edge[edgeN].c=-c; edge[edgeN].f=0;
     99     edge[edgeN].next=first[v]; first[v]=edgeN++;
    100 }
    101 
    102 int main()
    103 {
    104    int i, j;
    105    while(scanf("%d%d", &n, &k)!=EOF)
    106    {
    107       maxFlow=0;
    108       edgeN=0;
    109       memset(first, -1, sizeof(first));
    110       s=0; t=n*n*2+1;
    111       for(i=1; i<=n; ++i)
    112         for(j=1; j<=n; ++j)
    113           scanf("%d", &cap[i][j]);
    114       adde(s, 1, 0, k);
    115       for(i=1; i<=n; ++i)
    116         for(j=1; j<=n; ++j)//n*n个节点,拆点之后变成2*n*n个节点 
    117         {
    118            int nb=(i-1)*n+j;
    119            adde(2*nb-1, 2*nb, -cap[i][j], 1);//注意:a到a`是建立两条边,但是两条边的费用和容量不一样 
    120            adde(2*nb-1, 2*nb, 0, k-1);
    121            if(j<n)//向右建图 
    122              adde(2*nb, 2*(nb+1)-1, 0, k);
    123            if(i<n)//向下建图 
    124              adde(2*nb, 2*(nb+n)-1, 0, k);
    125     }
    126        adde(n*n*2, t, 0, k);
    127        
    128        while(spfa())//建好图之后,直接调用最小费用最大流模板就好了 
    129           updateFlow();
    130        printf("%d
    ", -maxFlow);
    131    }
    132    return 0;
    133 }
  • 相关阅读:
    安全测试基础知识
    Python思维导图(一)—— 基础
    Java 高级点的东西
    安全测试通用用例
    测试基础篇(一)—— 面试终极常见
    测试基础篇(二)—— 面试挺常见
    差分约束基本讲解
    0x42 数据结构进阶树状数组
    Codeforce Problem 711A Bus to Udayland (正则表达式)
    POJ 1456 Supermarket【贪心 + 并查集】
  • 原文地址:https://www.cnblogs.com/hujunzheng/p/3798997.html
Copyright © 2020-2023  润新知