CodeForces 821D Okabe and City

Okabe and City

题解:

将行和列也视为一个点。 然后从普通的点走到行/列的点的话,就代表这行/列已经被点亮了。

然后将费用为0的点建上边。

注意讨论(n,m)非亮的情况下。

代码:

#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod =  (int)1e9+7;
const int N = 1e5 + 100;
const int M = 6E5 + 100;
int x[N], y[N];
vector<int> vx[N], vy[N];
bool cmpx(int a, int b){
    return y[a] < y[b];
}
bool cmpy(int a, int b){
    return x[a] < x[b];
}
int head[N], to[M], nt[M], ct[M], tot;
void add(int u, int v, int w){
    to[tot] = v; ct[tot] = w;
    nt[tot] = head[u]; head[u] = tot++;
}
priority_queue<pll, vector<pll>, greater<pll> > pq;
int dis[N];
int main(){
    memset(head, -1, sizeof head);
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    int f = 0, b;
    for(int i = 1; i <= k; ++i){
        scanf("%d%d", &x[i], &y[i]);
        if(x[i] == n && y[i] == m) f = i;
        if(x[i] == 1 && y[i] == 1) b = i;
        vx[x[i]].pb(i);
        vy[y[i]].pb(i);
    }
    for(int i = 1; i <= n; ++i){
        sort(vx[i].begin(), vx[i].end(), cmpx);
        for(int j = 1; j < vx[i].size(); ++j){
            int p = vx[i][j-1], n = vx[i][j];
            if(y[n] == y[p] + 1) {
                add(n, p, 0);
                add(p, n, 0);
            }
        }
        for(int x : vx[i]){
            if(i>1) add(x, k+i-1, 1);
            add(x, k+i, 1);
            if(i<n) add(x, k+i+1, 1);
        }
        for(int x : vx[i]){
            add(k+i, x, 0);
        }
        if(i > 1){
            for(int x : vx[i-1]){
                add(k+i, x, 0);
            }
        }
        if(i < n){
            for(int x : vx[i+1]){
                add(k+i, x, 0);
            }
        }
    }
    for(int i = 1; i <= m; ++i){
        sort(vy[i].begin(), vy[i].end(), cmpy);
        for(int j = 1; j < vy[i].size(); ++j){
            int p = vy[i][j-1], n = vy[i][j];
            if(x[n] == x[p] + 1){
                add(n, p, 0);
                add(p, n, 0);
            }
        }
        for(int x : vy[i]){
            if(i > 1) add(x, k+n+i-1, 1);
            add(x, k+n+i, 1);
            if(i < m) add(x, k+n+i+1, 1);
        }
        for(int x : vy[i]){
            add(k+i+n, x, 0);
        }
        if(i > 1){
            for(int x : vy[i-1]){
                add(k+i+n, x, 0);
            }
        }
        if(i < n){
            for(int x : vy[i+1]){
                add(k+i+n, x, 0);
            }
        }
    }
    if(!f){
        f = k+1+n+m;
        add(k+n, f, 0);
        add(k+n+m, f, 0);
    }
    memset(dis, inf, sizeof dis);
    pq.push({0,b});/// id, c, cost
    dis[b] = 0;
    while(!pq.empty()){
        pll now = pq.top();
        pq.pop();
        int u = now.se, cost = now.fi;
            if(dis[u] != cost) continue;
        if(u == f){
            cout << cost << endl;
            return 0;
        }
        for(int i = head[u]; ~i; i = nt[i]){
            int v = to[i], w = ct[i];
            if(dis[v] > dis[u] + w){
                dis[v] = dis[u] + w;
                pq.push({dis[v], v});
            }
        }
    }
    puts("-1");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/MingSD/p/11110609.html