zoukankan      html  css  js  c++  java
  • 洛谷 P2045 方格取数加强版【费用流】

     
     
    题目链接:https://www.luogu.org/problemnew/show/P2045

    题目描述

    给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大

    输入输出格式

    输入格式:

    第一行两个数n,k(1<=n<=50, 0<=k<=10)

    接下来n行,每行n个数,分别表示矩阵的每个格子的数

    输出格式:

    一个数,为最大和

    输入输出样例

    输入样例#1:
    3 1
    1 2 3
    0 2 1
    1 4 2
    输出样例#1:
    11

    说明

    每个格子中的数不超过1000

    题解:和昨天那题略像,就是限制点了,拆点再跑费用流。。。不写了,我上课去......

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N = 5010;//注意点数
     5 const int M = N*8+10;
     6 const int INF = 0x3f3f3f3f;
     7 struct Edge { int to,next,cap,flow,cost; }edge[M];
     8 int head[N],tol;
     9 int pre[N],dis[N];
    10 bool vis[N];
    11 int V;      
    12 void init(int n) {
    13     V = n;
    14     tol = 0;
    15     memset(head,-1,sizeof(head));
    16 }
    17 void addedge(int u,int v,int cap,int cost) {
    18     edge[tol].to = v; edge[tol].cap = cap; edge[tol].cost = cost; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++;
    19     edge[tol].to = u; edge[tol].cap = 0; edge[tol].cost = -cost; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++;
    20 }
    21 bool spfa(int s,int t) {
    22     queue<int>q;
    23     for(int i = 0;i < V;i++) {
    24         dis[i] = INF;
    25         vis[i] = false;
    26         pre[i] = -1;
    27     }
    28     dis[s] = 0;
    29     vis[s] = true;
    30     q.push(s);
    31     while(!q.empty()) {
    32         int u = q.front();
    33         q.pop();
    34         vis[u] = false;
    35         for(int i = head[u]; i != -1;i = edge[i].next) {
    36             int v = edge[i].to;
    37             if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost ) {
    38                 dis[v] = dis[u] + edge[i].cost;
    39                 pre[v] = i;
    40                 if(!vis[v]) {
    41                     vis[v] = true;
    42                     q.push(v);
    43                 }
    44             }
    45         }
    46     }
    47     if(pre[t] == -1) return false;
    48     else return true;
    49 }
    50 int minCostMaxflow(int s,int t,int &cost) {
    51     int flow = 0;
    52     cost = 0;
    53     while(spfa(s,t)) {
    54         int Min = INF;
    55         for(int i = pre[t];i != -1;i = pre[edge[i^1].to]) {
    56             if(Min > edge[i].cap - edge[i].flow)
    57                 Min = edge[i].cap - edge[i].flow;
    58         }
    59         for(int i = pre[t];i != -1;i = pre[edge[i^1].to]) {
    60             edge[i].flow += Min;
    61             edge[i^1].flow -= Min;
    62             cost += edge[i].cost * Min;
    63         }
    64         flow += Min;
    65     }
    66     return flow;
    67 }
    68 int main() {
    69     int n, k, i, j, x, ans = 0;
    70     scanf("%d%d", &n, &k);
    71     init(n*n*2+3);
    72 
    73     int s = n*n*2+1, t = n*n*2+2;
    74 
    75     for(i = 1; i <= n; ++i) {//拆点限流
    76         for(j = 1; j <= n; ++j) {
    77             scanf("%d", &x);
    78             addedge((i-1)*n+j, (i-1)*n+j + n*n, 1, -x);//存负权
    79             if(k > 1) addedge((i-1)*n+j, (i-1)*n+j + n*n, k-1, 0);//注意判断
    80         }
    81     }
    82     for(i = 1; i <= n ;++i) {//向右加边
    83         for(j = 1; j < n; ++j) {
    84             addedge((i-1)*n+j + n*n, (i-1)*n+j+1, k, 0);
    85         }
    86     }
    87     for(i = 1; i < n; ++i) {//向下加边
    88         for(j = 1; j <= n; ++j) {
    89             addedge((i-1)*n+j + n*n, (i-1)*n+j+n, k, 0);
    90         }
    91     }
    92     //源点、汇点 与 起点、终点连边
    93     addedge(s, 1, k, 0);
    94     addedge(n*n*2, t, k, 0);
    95 
    96     minCostMaxflow(s, t, ans);
    97     printf("%d
    ", -ans);
    98     return 0;
    99 }
    View Code
  • 相关阅读:
    POJ3159 Candies —— 差分约束 spfa
    POJ1511 Invitation Cards —— 最短路spfa
    POJ1860 Currency Exchange —— spfa求正环
    POJ3259 Wormholes —— spfa求负环
    POJ3660 Cow Contest —— Floyd 传递闭包
    POJ3268 Silver Cow Party —— 最短路
    POJ1797 Heavy Transportation —— 最短路变形
    POJ2253 Frogger —— 最短路变形
    POJ1759 Garland —— 二分
    POJ3685 Matrix —— 二分
  • 原文地址:https://www.cnblogs.com/GraceSkyer/p/9039340.html
Copyright © 2011-2022 走看看