CodeForces 821D Okabe and City
题解:
将行和列也视为一个点。 然后从普通的点走到行/列的点的话,就代表这行/列已经被点亮了。
然后将费用为0的点建上边。
注意讨论(n,m)非亮的情况下。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }