码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 2686

时间:2016-08-22 14:57:02      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:

http://acm.split.hdu.edu.cn/showproblem.php?pid=2686

 

and

 

http://codevs.cn/problem/1169/

 

题意: 从矩阵左上角1,1,走到右下角n,n,每次只能向右或向下走,到达nn后,再走回1,1,往回走时,每次只能向左或者向上走,除了11和nn,其他点在去和回的路径中只能出现一次,问权值和最大的来回的路径是多少。

解法:找一条来回的路径,相当于从11到nn找两条点不重复的路径,使得两条的和最大。 相当于从源点 给11一个2的流量, nn给汇点一个n的流量, 跑最大流, 两个流经过的两条路就是要找的答案。 为了保证一个点只会被选择一次,考虑拆点。

把矩阵中的点xy,拆成两个点,一个称为in,一个称为out,所有指向这个点的边 连到in,所有从xy出发的边,从out点连出去, in-》out连流量为1,费用为- a【x】【y】,求最小费用最大流, 相反数就是最大权值和。其他的边就是往右和往下建边。

 

技术分享
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int inf=0x3f3f3f3f;
  4 const int M=1e2+10;
  5 class MaxFlowMinCost { ///最小费用最大流O(~=V^3)
  6     typedef int typef;///流量的类型
  7     typedef int typec;///费用的类型
  8     static const int ME=1e6+10;///边的个数
  9     static const int MV=5e3+10;///点的个数
 10     queue<int> q;
 11     int n,cur[MV],pre[MV];
 12     bool used[MV],sign[MV];
 13     typef flow;
 14     typec cost,dist[MV];
 15     bool spfa(int s,int t) {
 16         for(int i=0; i<=n; i++) {
 17             used[i]=sign[i]=dist[i]=0;
 18         }
 19         used[s]=sign[s]=true;
 20         while(!q.empty()) q.pop();
 21         q.push(s);
 22         while(!q.empty()) {
 23 //            - 24 -
 24             int u=q.front();
 25             q.pop();
 26             used[u]=false;
 27             for(int i=g.head[u]; ~i; i=g.e[i].next) {
 28                 if(g.e[i].flow<1) continue;
 29                 int v=g.e[i].v;
 30                 typec c=g.e[i].cost;
 31                 if(!sign[v]||dist[v]>dist[u]+c) {
 32                     dist[v]=dist[u]+c;
 33                     sign[v]=true;
 34                     pre[v]=u;
 35                     cur[v]=i;
 36                     if(used[v]) continue;
 37                     used[v]=true;
 38                     q.push(v);
 39                 }
 40             }
 41         }
 42         return sign[t];
 43     }
 44     struct G {
 45         struct E {
 46             int v,next;
 47             typef flow;
 48             typec cost;
 49         } e[ME];
 50         int le,head[MV];
 51         void init(int n) {
 52             le=0;
 53             for(int i=0; i<=n; i++) head[i]=-1;
 54         }
 55         void add(int u,int v,typef flow,typec cost) {
 56             e[le].v=v;
 57             e[le].flow=flow;
 58             e[le].cost=cost;
 59             e[le].next=head[u];
 60             head[u]=le++;
 61         }
 62     } g;
 63 public:
 64     void init(int tn) {
 65         n=tn;
 66         g.init(n);
 67     }
 68 //    - 25 -
 69     void add(int u,int v,typef flow,typec cost) {
 70         g.add(u,v,flow,cost);
 71         g.add(v,u,0,-cost);
 72     }
 73     void solve(int s,int t) {
 74         flow=cost=0;
 75         while(spfa(s,t)) {
 76             int temp=t;
 77             typef now=inf;
 78             while(temp!=s) {
 79                 now=min(now,g.e[cur[temp]].flow);
 80                 temp=pre[temp];
 81             }
 82             flow+=now;
 83             temp=t;
 84             while(temp!=s) {
 85                 int id=cur[temp];
 86                 cost+=now*g.e[id].cost;
 87                 g.e[id].flow-=now;
 88                 g.e[id^1].flow+=now;
 89                 temp=pre[temp];
 90             }
 91         }
 92     }
 93     typef getflow() {
 94         return flow;
 95     }
 96     typec getcost() {
 97         return cost;
 98     }
 99 } gx;
100 int a[M][M];
101 int in[M][M];
102 int out[M][M];
103 int n,m;
104 int solve() {
105     int id=0;
106     for(int i=0; i<n; i++) {
107         for(int j=0; j<m; j++) {
108             in[i][j]=id;
109             id++;
110         }
111     }
112     for(int i=0; i<n; i++) {
113         for(int j=0; j<m; j++) {
114             out[i][j]=id;
115             id++;
116         }
117     }
118     int s=id;
119     id++;
120     int t=id;
121     id++;
122     gx.init(t);
123     gx.add(s,in[0][0],2,0);
124     gx.add(out[n-1][m-1],t,2,0);
125     for(int i=0; i<n; i++) {
126         for(int j=0; j<m; j++) {
127             int flow=1;
128             if(i==0&&j==0) flow=2;
129             if(i==n-1&&j==m-1) flow=2;
130             gx.add(in[i][j],out[i][j],flow,-a[i][j]);
131             if(i+1<n) {
132                 gx.add(out[i][j],in[i+1][j],1,0);
133             }
134             if(j+1<m) {
135                 gx.add(out[i][j],in[i][j+1],1,0);
136             }
137         }
138     }
139     gx.solve(s,t);
140     return -gx.getcost();
141 }
142 int main() {
143     while(~scanf("%d",&n)) {
144         m=n;
145         for(int i=0; i<n; i++) {
146             for(int j=0; j<m; j++) {
147                 scanf("%d",&a[i][j]);
148             }
149         }
150         printf("%d\n",solve()-a[0][0]-a[n-1][n-1]);
151     }
152     return 0;
153 }
View Code

 

有另一种动态规划解法,网上称之为多线程dp。 

 

end 

HDU 2686

标签:

原文地址:http://www.cnblogs.com/cs1131/p/5795588.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!