[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;
    
}

 

posted @ 2019-01-04 22:28  evenbao  阅读(195)  评论(0编辑  收藏  举报