BZOJ2007——[Noi2010]海拔

时间:2023-11-27 16:19:50

1、题意:一个裸的最小割

2、分析:直接转成对偶图最短路就好了,水爆了!(雾)

#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 2000010
#define inf 1014748364

inline int read(){
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
} 

namespace dijkstra{
    struct Edge{
        int u, v, w, next;
    } G[M];
    int head[M], tot;

    struct Node{
        int d, u;

        inline bool operator < (const Node& rhs) const{
            return d > rhs.d;
        }
    };
    priority_queue<Node> Q;
    int d[M];
    bool done[M];

    inline void init(){
        memset(head, -1, sizeof(head));
        tot = 0;
    }

    inline void add(int u, int v, int w){
    //  printf("%d %d %d\n", u, v, w);
        G[++ tot] = (Edge){u, v, w, head[u]};
        head[u] = tot;
    }

    inline int get_dis(int s, int t, int n){
        memset(done, 0, sizeof(done));
        for(int i = 0; i <= n; i ++) d[i] = inf;
        d[s] = 0;
        Q.push((Node){0, s});
        while(!Q.empty()){
            Node u = Q.top(); Q.pop();
            int x = u.u;
            if(done[x]) continue;
            done[x] = 1;
            for(int i = head[x]; i != -1; i = G[i].next){
                Edge& e = G[i];
                if(d[e.v] > d[x] + e.w){
                    d[e.v] = d[x] + e.w;
                    Q.push((Node){d[e.v], e.v});
                }
            }
        }
        return d[t];
    }
}

using namespace dijkstra;

int n;

inline int num(int i, int j){
    if(j < 1 || i > n) return 0;
    if(i < 1 || j > n) return n * n + 1;
    return (i - 1) * n + j;
}

int main(){
    n = read();
    init();
    for(int i = 0; i <= n; i ++){
        for(int j = 1; j <= n; j ++){
            int x = read();
            add(num(i + 1, j), num(i, j), x);
        }
    }
    for(int i = 1; i <= n; i ++){
        for(int j = 0; j <= n; j ++){
            int x = read();
            add(num(i, j), num(i, j + 1), x);
        }
    }
    for(int i = 0; i <= n; i ++){
        for(int j = 1; j <= n; j ++){
            int x = read();
            add(num(i, j), num(i + 1, j), x);
        }
    }
    for(int i = 1; i <= n; i ++){
        for(int j = 0; j <= n; j ++){
            int x = read();
            add(num(i, j + 1), num(i, j), x);
        }
    }
    printf("%d\n", get_dis(0, n * n + 1, n * n + 1));
    return 0;
}