• HDU 2686 MCMF


    题意:两遍最长路,不能走重复点。和UVA 10806类似。

    分析:拆点,u->u',MCMF,求的是最大流的最小费用,那么cost取负。

    注意的是源点,源点不用拆,那么走出来的最小费用,左上角的点,右下角的点走了两遍,输出除去即可。

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 const int maxn = 2500+5;
      6 const int INF = 0x3f3f3f3f;
      7 
      8 struct Edge
      9 {
     10     int from, to, cap, flow, cost;
     11 };
     12 
     13 struct MCMF
     14 {
     15     int n, m;
     16     vector<Edge> edges;
     17     vector<int> G[maxn];
     18     bool inq[maxn];         // 是否在队列中
     19     int d[maxn];           // Bellman-Ford
     20     int p[maxn];           // 上一条弧
     21     int a[maxn];           // 可改进量
     22 
     23     void init(int n)
     24     {
     25         this->n = n;
     26         for(int i = 0; i < n; i++) G[i].clear();
     27         edges.clear();
     28     }
     29 
     30     void AddEdge(int from, int to, int cap, int cost)
     31     {
     32         edges.push_back((Edge)
     33         {
     34             from, to, cap, 0, cost
     35         });
     36         edges.push_back((Edge)
     37         {
     38             to, from, 0, 0, -cost
     39         });
     40         m = edges.size();
     41         G[from].push_back(m-2);
     42         G[to].push_back(m-1);
     43     }
     44 
     45     bool BellmanFord(int s, int t, int &flow, long long& cost)
     46     {
     47         memset(inq,0,sizeof(inq));
     48         for(int i=0;i<n;i++)
     49             d[i] = INF;
     50         d[s] = 0;
     51         inq[s] = true;
     52         p[s] = 0;
     53         a[s] = INF;
     54 
     55         queue<int> Q;
     56         Q.push(s);
     57         while(!Q.empty())
     58         {
     59             int u = Q.front();
     60             Q.pop();
     61             inq[u] = false;
     62             for(int i = 0; i < G[u].size(); i++)
     63             {
     64                 Edge& e = edges[G[u][i]];
     65                 if(e.cap > e.flow && d[e.to] > d[u] + e.cost)
     66                 {
     67                     d[e.to] = d[u] + e.cost;
     68                     p[e.to] = G[u][i];
     69                     a[e.to] = min(a[u], e.cap - e.flow);
     70                     if(!inq[e.to])
     71                     {
     72                         Q.push(e.to);
     73                         inq[e.to] = true;
     74                     }
     75                 }
     76             }
     77         }
     78         if(d[t] == INF) return false; //s-t 不连通,失败退出
     79         flow += a[t];
     80         cost += (long long)d[t] * (long long)a[t];
     81         int u = t;
     82         while(u != s)
     83         {
     84             edges[p[u]].flow += a[t];
     85             edges[p[u]^1].flow -= a[t];
     86             u = edges[p[u]].from;
     87         }
     88         return true;
     89     }
     90 
     91     long long Mincost(int s, int t)
     92     {
     93         long long cost = 0;
     94         int flow = 0;
     95         while(BellmanFord(s, t, flow, cost)) {
     96             if(flow==2)
     97                 break;
     98         };
     99         return cost;
    100     }
    101 }sol;
    102 
    103 int maps[maxn][maxn];
    104 int aa[maxn*maxn];
    105 
    106 int main()
    107 {
    108     //freopen("in.txt","r",stdin);
    109     int n;
    110     while(scanf("%d",&n)!=EOF) {
    111 
    112         for(int i=0;i<n;i++)
    113             for(int j=0;j<n;j++)
    114                 scanf("%d",&maps[i][j]);
    115 
    116         int s = 0,t = n*n-1;
    117         sol.init(n*n*2);
    118 
    119         for(int i=0;i<n;i++) {
    120             for(int j=0;j<n;j++) {
    121                 int id = i*n + j;
    122                 if(id!=s&&id!=t)
    123                     sol.AddEdge(id,id+n*n,1,-maps[i][j]);
    124                 if(id==s) {
    125                     sol.AddEdge(id,id+1,1,0);
    126                     sol.AddEdge(id,id+n,1,0);
    127                 }
    128                 else {
    129                     if(i<n-1) sol.AddEdge(id+n*n,id+n,1,0);
    130                     if(j<n-1) sol.AddEdge(id+n*n,id+1,1,0);
    131                 }
    132             }
    133         }
    134 
    135         printf("%d
    ",-sol.Mincost(s,t)+maps[0][0]+maps[n-1][n-1]);
    136 
    137 
    138 
    139     }
    140     return 0;
    141 }
    View Code
  • 相关阅读:
    P3501 [POI2010]ANT-Antisymmetry
    P3498 [POI2010]KOR-Beads(hash表)
    UVA10298 Power Strings
    UVA1714 Keyboarding(bfs)
    P4289 [HAOI2008]移动玩具(bfs)
    Ubuntu分辨率太小的解决方案
    Ubuntu分辨率太小的解决方案
    主板亮红灯,显示器没信号
    主板亮红灯,显示器没信号
    VS注释与取消注释快捷键
  • 原文地址:https://www.cnblogs.com/TreeDream/p/7211719.html
Copyright © 2020-2023  润新知