[PA 2011] Journeys
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=3073
[算法]
考虑线段树优化建图
建立两棵线段树 , 一棵为入树 , 一棵为出树 ,连边时 , 我们只需建立超级点S , 将区间[A , B]与点S连边 , 点S与区间[C , D]连边
然后使用01BFS或Dijkstra算法求解最短路即可
时间复杂度 : O(NlogN)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 500010 const int inf = 1e9; typedef long long ll; typedef long double ld; typedef unsigned long long ull; struct Node { int lc , rc; } a[MAXN * 4]; int cnt , tot , n , m , P; int root[2] , head[MAXN * 10] , dist[MAXN * 10] , to[MAXN * 60] , nxt[MAXN * 60]; bool visited[MAXN * 10] , w[MAXN * 60]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void addedge(int u , int v , int c) { ++cnt; to[cnt] = v; w[cnt] = c; nxt[cnt] = head[u]; head[u] = cnt; } inline void buildA(int &now , int l , int r) { if (l != r) now = ++tot; else { now = l; return; } int mid = (l + r) >> 1; buildA(a[now].lc , l , mid); buildA(a[now].rc , mid + 1 , r); addedge(a[now].lc , now , 0); addedge(a[now].rc , now , 0); } inline void buildB(int &now , int l , int r) { if (l != r) now = ++tot; else { now = l; return; } int mid = (l + r) >> 1; buildB(a[now].lc , l , mid); buildB(a[now].rc , mid + 1 , r); addedge(now , a[now].lc , 0); addedge(now , a[now].rc , 0); } inline void updateB(int now , int l , int r , int ql , int qr , int s) { if (l == ql && r == qr) addedge(s , now , 1); else { int mid = (l + r) >> 1; if (mid >= qr) updateB(a[now].lc , l , mid , ql , qr , s); else if (mid + 1 <= ql) updateB(a[now].rc , mid + 1 , r , ql , qr , s); else { updateB(a[now].lc , l , mid , ql , mid , s); updateB(a[now].rc , mid + 1 , r , mid + 1 , qr , s); } } } inline void updateA(int now , int l , int r , int ql , int qr , int s) { if (l == ql && r == qr) addedge(now , s , 1); else { int mid = (l + r) >> 1; if (mid >= qr) updateA(a[now].lc , l , mid , ql , qr , s); else if (mid + 1 <= ql) updateA(a[now].rc , mid + 1 , r , ql , qr , s); else { updateA(a[now].lc , l , mid , ql , mid , s); updateA(a[now].rc , mid + 1 , r , mid + 1 , qr , s); } } } inline void dijkstra(int S) { priority_queue< pair<int , int> , vector< pair<int , int> > , greater< pair<int , int> > > q; for (int i = 1; i <= tot; i++) dist[i] = inf; q.push(make_pair(0 , S)); dist[S] = 0; while (!q.empty()) { int cur = q.top().second; q.pop(); if (visited[cur]) continue; visited[cur] = true; for (int i = head[cur]; i; i = nxt[i]) { int v = to[i] , c = w[i]; if (dist[cur] + c < dist[v]) { dist[v] = dist[cur] + c; q.push(make_pair(dist[v] , v)); } } } } int main() { read(n); read(m); read(P); tot = n; buildA(root[0] , 1 , n); buildB(root[1] , 1 , n); for (int i = 1; i <= m; i++) { int A , B , C , D; read(A); read(B); read(C); read(D); updateA(root[0] , 1 , n , A , B , ++tot); updateB(root[1] , 1 , n , C , D , tot); updateA(root[0] , 1 , n , C , D , ++tot); updateB(root[1] , 1 , n , A , B , tot); } dijkstra(P); for (int i = 1; i <= n; i++) printf("%d\n" , dist[i] >> 1); return 0; }