zoukankan      html  css  js  c++  java
  • HDU 3376 费用流 Matrix Again

    题意:

    给出一个n × n的矩阵,每个格子中有一个数字代表权值,找出从左上角出发到右下角的两条不相交的路径(起点和终点除外),使得两条路径权值之和最大。

    分析:

    如果n比较小的话是可以DP的,但是现在n非常大,DP会超时的。

    这个用费用流来求解:

    因为每个点只能走一次,所以先拆点,两点之间连一条容量为1费用为对应格子权值的边,如果是起点或终点,因为要走两次,所以要连容量为2的边。

    对于不同格子之间,如果能到达,连一条容量为INF,费用为0的边。

    因为算法求的是最小费用,所以我们把每个格子的相反数当做费用去连边,最后再取相反数。

    因为起点和终点容量为2,计算出来的最大权值重复计算了左上角和右下角的权值,所以答案应该再减去这两个数。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <queue>
      7 using namespace std;
      8 
      9 const int maxn = 600;
     10 const int maxnode = maxn * maxn * 2;
     11 const int maxm = 1000000 + 10;
     12 const int INF = 0x3f3f3f3f;
     13 
     14 struct Edge
     15 {
     16     int from, to, cap, flow, cost;
     17     int nxt;
     18     Edge() {}
     19     Edge(int u, int v, int cap, int f, int cost, int nxt):from(u), to(v), cap(cap), flow(f), cost(cost), nxt(nxt) {}
     20 };
     21 
     22 int ecnt;
     23 Edge edges[maxm << 2];
     24 int head[maxnode];
     25 
     26 void AddEdge(int u, int v, int cap, int cost)
     27 {
     28     edges[ecnt] = Edge(u, v, cap, 0, cost, head[u]);
     29     head[u] = ecnt++;
     30     edges[ecnt] = Edge(v, u, 0, 0, -cost, head[v]);
     31     head[v] = ecnt++;
     32 }
     33 
     34 int row;
     35 int A[maxn][maxn];
     36 
     37 int n;
     38 int d[maxnode + 10], p[maxnode + 10], a[maxnode + 10];
     39 bool inq[maxnode + 10];
     40 
     41 bool SPFA(int s, int t)
     42 {
     43     memset(inq, false, sizeof(inq));
     44     memset(p, -1, sizeof(p));
     45     memset(d, 0x3f, sizeof(d));
     46     inq[s] = true;
     47     d[s] = 0;
     48     a[s] = INF;
     49 
     50     queue<int> Q;
     51     Q.push(s);
     52     while(!Q.empty())
     53     {
     54         int u = Q.front(); Q.pop(); inq[u] = false;
     55         for(int i = head[u]; ~i; i = edges[i].nxt)
     56         {
     57             Edge& e = edges[i];
     58             int v = e.to;
     59             if(e.flow < e.cap && d[u] + e.cost < d[v])
     60             {
     61                 d[v] = d[u] + e.cost;
     62                 p[v] = i;
     63                 a[v] = min(a[u], e.cap - e.flow);
     64                 if(!inq[v]) { inq[v] = true; Q.push(v); }
     65             }
     66         }
     67     }
     68 
     69     return d[t] != INF;
     70 }
     71 
     72 int Mincost(int s, int t)
     73 {
     74     int flow = 0;
     75     int cost = 0;
     76     while(SPFA(s, t))
     77     {
     78         flow += a[t];
     79         cost += d[t] * a[t];
     80         int u = t;
     81         while(u != s)
     82         {
     83             edges[p[u]].flow += a[t];
     84             edges[p[u]^1].flow -= a[t];
     85             u = edges[p[u]].from;
     86         }
     87     }
     88     return cost;
     89 }
     90 
     91 int main()
     92 {
     93     while(scanf("%d", &row) == 1)
     94     {
     95         for(int i = 0; i < row; i++)
     96             for(int j = 0; j < row; j++) scanf("%d", &A[i][j]);
     97 
     98         n = row * row;
     99         int s = 0, t = n * 2 - 1;
    100         ecnt = 0;
    101         memset(head, -1, sizeof(head));
    102 
    103         //build graph
    104         for(int i = 0; i < row; i++)
    105             for(int j = 0; j < row; j++)
    106             {
    107                 int u = i * row + j;
    108                 int v = u + n;
    109                 int cap = 1;
    110                 if(u == 0 || u == n - 1) cap++;
    111                 AddEdge(u, v, cap, -A[i][j]);
    112 
    113                 int w;
    114                 if(i < row - 1)
    115                 {
    116                     w = u + row;
    117                     AddEdge(v, w, INF, 0);
    118                 }
    119                 if(j < row - 1)
    120                 {
    121                     w = u + 1;
    122                     AddEdge(v, w, INF, 0);
    123                 }
    124             }
    125 
    126         n <<= 1;
    127         printf("%d
    ", -Mincost(s, t) - A[0][0] - A[row-1][row-1]);
    128     }
    129 
    130     return 0;
    131 }
    代码君
  • 相关阅读:
    International Collegiate Programming Contest 2019 Latin American Regional Contests E. Eggfruit Cake(思维/尺取)
    Codeforces Round #673 (Div. 2) C. k-Amazing Numbers(思维)
    2020 计蒜之道 预赛 第一场 A、B
    生成字符画
    我对目前国内教学的看法
    Stm32 调试时发生HardFault_Handler
    python异常处理
    windows nfs客户端配置
    linux服务器删除文件后df -h查看文件系统占比无变化
    python ssh小程序
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4790006.html
Copyright © 2011-2022 走看看