zoukankan      html  css  js  c++  java
  • BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS

    BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS

    Description

    Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路。N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a,b),(c,d)表示,对于任意两个国家x,y,如果a<=x<=b,c<=y<=d,那么在xy之间建造一条道路。Seter保证一条道路不会修建两次,也保证不会有一个国家与自己之间有道路。
    Seter好不容易建好了所有道路,他现在在位于P号的首都。Seter想知道P号国家到任意一个国家最少需要经过几条道路。当然,Seter保证P号国家能到任意一个国家。
    注意:可能有重边

    Input

    第一行三个数N,M,P。N<=500000,M<=100000。
    后M行,每行4个数A,B,C,D。1<=A<=B<=N,1<=C<=D<=N。

     

    Output

    N行,第i行表示P号国家到第i个国家最少需要经过几条路。显然第P行应该是0。

    Sample Input

    5 3 4
    1 2 4 5
    5 5 4 4
    1 1 3 3

    Sample Output

    1
    1
    2
    0
    1

    有一个朴素的方法:对(a,b)中的点对一个新建节点连边边权为0,对另一个新建节点连边权为1,另一个新建节点向(c,d)中的所有节点连边。
    用线段树优化一下:
    开两个线段树A,B,其中A中的节点向父亲连边,B中节点向儿子连边。B中叶子向A中叶子连边。
    然后把(a,b)中的点替换成线段树上的log个节点,和上面的连边方法相同。
    跑最短路即可,由于边权是0,1可以BFS上去。
     
    代码:
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 500050
    #define M 4000050
    int Q[M],tot,l,r,ls[N<<3],rs[N<<3];
    int head[M][2],to[M<<2][2],nxt[M<<2][2],cnt,idx[N],n,m,a[N<<3],dis[M],rta,rtb,b[N<<3];
    inline void add(int u,int v,int w) {
        to[++cnt][w]=v; nxt[cnt][w]=head[u][w]; head[u][w]=cnt;
    }
    void build(int l,int r,int &p,int flg) {
        p=++tot;
        if(l==r) {
            if(!flg) idx[l]=p;
            else b[l]=p;
            return ;
        }
        int mid=(l+r)>>1;
        build(l,mid,ls[p],flg); build(mid+1,r,rs[p],flg);
        if(!flg) {
            add(ls[p],p,0); add(rs[p],p,0);
        }else {
            add(p,ls[p],0); add(p,rs[p],0);
        }
    }
    void update(int l,int r,int x,int y,int p) {
        if(x<=l&&y>=r) {
            a[++a[0]]=p; return ;
        }
        int mid=(l+r)>>1;
        if(x<=mid) update(l,mid,x,y,ls[p]);
        if(y>mid) update(mid+1,r,x,y,rs[p]);
    }
    void link(int x,int y,int z,int w) {
        tot++;
        update(1,n,x,y,rta);
        int i;
        for(i=1;i<=a[0];i++) add(a[i],tot,0); a[0]=0;
        tot++; add(tot-1,tot,1);
        update(1,n,z,w,rtb);
        for(i=1;i<=a[0];i++) add(tot,a[i],0); a[0]=0;
    }
    void dfs(int x,int y) {
        if(dis[x]) return ;
        dis[x]=y;
        Q[r++]=x;
        int i;
        for(i=head[x][0];i;i=nxt[i][0]) dfs(to[i][0],y);
    }
    int main() {
        int S;int i,x,y,z,w;
        scanf("%d%d%d",&n,&m,&S);
        rta=0,rtb=0;
        build(1,n,rta,0); build(1,n,rtb,1);
        for(i=1;i<=n;i++) add(b[i],idx[i],0);
        for(i=1;i<=m;i++) {
            scanf("%d%d%d%d",&x,&y,&z,&w);
            link(x,y,z,w); link(z,w,x,y);
        }
        dfs(idx[S],1);
        while(l<r) {
            x=Q[l++];y=dis[x]+1;
            for(i=head[x][1];i;i=nxt[i][1]) dfs(to[i][1],y);
        }
        for(i=1;i<=n;i++) {
            printf("%d
    ",dis[idx[i]]-1);
        }
    }
    
  • 相关阅读:
    500桶酒中有一桶毒酒
    查看docker run参数(亲测实用)
    ubuntu密码忘记-备份
    python sklearn2pmml
    javafx弹窗显示错误堆栈
    Java实现新开一个进程
    MockServer调试通过,本地通过浏览器可以打开对应web网页
    java 实现Put request
    JAVA发送HttpClient请求及接收请求完整代码实例
    我还是很喜欢你
  • 原文地址:https://www.cnblogs.com/suika/p/9202158.html
Copyright © 2011-2022 走看看