Matrix Again HDU - 3376 (最大费用最大流+拆点)

Practice link:  https://vjudge.net/problem/HDU-3376

题意:给你一个 n*n 的矩阵,每个点有自身的权值,从左上角向右下角走只能向右或向下,从右下角向左上角走只能向左或向上,问你从左上角走向右下角再从右下角走向左上角且每个点只能走一次,问你最大权值之和是多少。

思路:首先从右下角到左上角的过程可以转化为从左上角到右下角,那么问题就变成了从左上角到右下角的两条没有重复点的路径的最大权值和。然后看到是走矩阵且要求权值之和最大且每个格子只能走一次,就想到最大费用最大流。首先建立超级源点和超级汇点,源点到左上角的点的流量为2,费用为 0,右下角的点到汇点的流量为 2 ,费用为 0,由于每个点只能走一次,那么我们就进行拆点,即把点 k 拆成两个点 k1 和 k2,这两个点之间的流量为 1 ,费用为点 k 的权值(除了左上角和右下角的两个点的流量需要为 2)。其余可以联通的点之间的流量为 1 ,费用为 0 即可。

         最后跑一遍最大费用最大流,又因为左上角和右下角的点经过了两次,最后答案要减去这两个点的权值。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<string>
  6 #include<vector>
  7 #include<stack>
  8 #include<bitset>
  9 #include<cstdlib>
 10 #include<cmath>
 11 #include<set>
 12 #include<list>
 13 #include<deque>
 14 #include<map>
 15 #include<queue>
 16 #define ll long long
 17 #define MOD 998244353
 18 #define INF 0x3f3f3f3f
 19 #define mem(a,x) memset(a,x,sizeof(a))
 20 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
 21 using namespace std;
 22 
 23 const int maxn = 800000;
 24 
 25 bool vis[maxn];
 26 int n,m,s,t;
 27 int dis[maxn],pre[maxn],last[maxn],flow[maxn],maxflow,maxcost;
 28 
 29 struct node{
 30     int to,nxt,flow,dis;  //flow流量 dis花费
 31 }edge[4*maxn];
 32 int head[4*maxn],cnt=0;
 33 
 34 void addl(int u,int v,int flow,int dis)
 35 {
 36     edge[cnt].to=v;
 37     edge[cnt].flow=flow;
 38     edge[cnt].dis=dis;
 39     edge[cnt].nxt=head[u];
 40     head[u]=cnt++;
 41 }
 42 
 43 bool spfa(int s,int t)
 44 {
 45     for(int i=0;i<=2*n*n+1;i++){
 46         dis[i]=-1;
 47         flow[i]=INF;
 48         vis[i]=0;
 49     }
 50     queue<int>q;
 51     q.push(s);
 52     vis[s]=1;
 53     dis[s]=0;
 54     pre[t]=-1;
 55     while(!q.empty()){
 56         int now=q.front();
 57         q.pop();
 58         vis[now]=0;
 59         for(int i=head[now];i!=-1;i=edge[i].nxt)
 60         {
 61             if(edge[i].flow>0&&dis[edge[i].to]<dis[now]+edge[i].dis)
 62             {
 63                 dis[edge[i].to]=dis[now]+edge[i].dis;
 64                 pre[edge[i].to]=now;
 65                 last[edge[i].to]=i;
 66                 flow[edge[i].to]=min(flow[now],edge[i].flow);
 67                 if(!vis[edge[i].to])
 68                 {
 69                     vis[edge[i].to]=1;
 70                     q.push(edge[i].to);
 71                 }
 72             }
 73         }
 74     }
 75     return pre[t]!=-1;
 76 }
 77 void MCMF()
 78 {
 79     while(spfa(s,t))
 80     {
 81         int now=t;
 82         maxflow+=flow[t];
 83         maxcost+=flow[t]*dis[t];
 84         while(now!=s)
 85         {
 86             edge[last[now]].flow-=flow[t];
 87             edge[last[now]^1].flow+=flow[t];
 88             now=pre[now];
 89         }
 90     }
 91 }
 92 int mp[605][605];
 93 int main()
 94 {
 95     while (scanf("%d",&n)!=EOF) {
 96         mem(head,-1);
 97         mem(pre,-1);
 98         cnt=0;
 99         maxflow=0;
100         maxcost=0;
101         s=0;
102         t=2*n*n+1;
103         addl(s,1,2,0);
104         addl(1,s,0,0);
105         for(int i=1;i<=n;i++){
106             for(int j=1;j<=n;j++){
107                 scanf("%d",&mp[i][j]);
108                 int num=(i-1)*n+j;
109                 if(i==j&&(num==1||num==n*n)){
110                     addl(num,num+n*n,2,mp[i][j]);
111                     addl(num+n*n,num,0,-mp[i][j]);
112                 }else{
113                     addl(num+n*n,num,0,-mp[i][j]);
114                     addl(num,num+n*n,1,mp[i][j]);
115                 }
116                 if(i+1<=n){
117                     addl(num+n*n,i*n+j,1,0);
118                     addl(i*n+j,num+n*n,0,0);
119                 }
120                 if(j+1<=n){
121                     addl(num+n*n,num+1,1,0);
122                     addl(num+1,num+n*n,0,0);
123                 }
124             }
125         }
126         addl(2*n*n,t,2,0);
127         addl(t,2*n*n,0,0);
128         MCMF();
129         printf("%d\n",maxcost-mp[1][1]-mp[n][n]);
130     }
131     return 0;
132 }

 

posted @ 2020-08-21 22:15  hachuochuo  阅读(205)  评论(0编辑  收藏  举报