//目录

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\n",-sol.Mincost(s,t)+maps[0][0]+maps[n-1][n-1]);
136 
137 
138 
139     }
140     return 0;
141 }
View Code

 

posted @ 2017-07-20 16:05  小草的大树梦  阅读(126)  评论(0编辑  收藏  举报