BZOJ 3073: [Pa2011]Journeys Dijkstra+线段树优化建图

复习一下线段树优化建图:
1.两颗线段树的叶子节点的编号是公用的.
2.每次连边是要建两个虚拟节点 $p1,p2$ 并在 $p1,p2$ 之间连边.

#include <bits/stdc++.h>  
#define N 8000034  
#define ls t[x].lson 
#define rs t[x].rson   
#define inf 1000000000 
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout) 
using namespace std;     
int edges,tot,n,m,s,rtin,rtout;     
int hd[N],to[N],nex[N],val[N],d[N],done[N];       
void addedge(int u,int v,int c) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;    
}
int newnode() 
{
    return ++tot; 
}  
struct Node
{
    int lson,rson; 
}t[N]; 
struct P 
{ 
    int u,dis;        
    P(int u=0,int dis=0):u(u),dis(dis){}    
    bool operator<(P b) const 
    {
        return b.dis<dis;      
    }
}; 
priority_queue<P>q;    
namespace segin
{  
    void build(int l,int r,int &x) 
    {
        if(l==r) 
        {
            x=l; 
            return; 
        } 
        else 
        {
            x=newnode(); 
        } 
        int mid=(l+r)>>1; 
        if(l<=mid) build(l,mid,ls),addedge(x,ls,0); 
        if(r>mid)  build(mid+1,r,rs),addedge(x,rs,0);       
    }  
    void Add(int l,int r,int x,int L,int R,int p) 
    {
        if(l>=L&&r<=R) 
        {
            addedge(p,x,0);   
            return; 
        } 
        int mid=(l+r)>>1; 
        if(L<=mid) Add(l,mid,ls,L,R,p); 
        if(R>mid)  Add(mid+1,r,rs,L,R,p);    
    }
};
namespace segout
{
    void build(int l,int r,int &x) 
    {
        if(l==r) 
        {
            x=l; 
            return; 
        } 
        else 
        {
            x=newnode(); 
        } 
        int mid=(l+r)>>1; 
        if(l<=mid) build(l,mid,ls),addedge(ls,x,0); 
        if(r>mid)  build(mid+1,r,rs),addedge(rs,x,0);       
    }  
    void Add(int l,int r,int x,int L,int R,int p) 
    {
        if(l>=L&&r<=R) 
        {
            addedge(x,p,0);   
            return; 
        } 
        int mid=(l+r)>>1; 
        if(L<=mid) Add(l,mid,ls,L,R,p); 
        if(R>mid)  Add(mid+1,r,rs,L,R,p);    
    }
}; 
void Add(int l1,int r1,int l2,int r2,int w) 
{
    int p1=newnode(),p2=newnode();    
    addedge(p1,p2,w);  
    segout::Add(1,n,rtout,l1,r1,p1);      
    segin::Add(1,n,rtin,l2,r2,p2);              
}
void Dijkstra() 
{  
    for(int i=0;i<N;++i) d[i]=inf; 
    for(d[s]=0,q.push(P(s,0));!q.empty();)   
    { 
        P e=q.top();    
        q.pop(); 
        int u=e.u;   
        if(done[u]) continue;   
        done[u]=1;     
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i]; 
            if(d[v]>d[u]+val[i]) 
            {
                d[v]=d[u]+val[i]; 
                q.push(P(v,d[v]));         
            }
        }
    }
}
int main() 
{  
    int i,j; 
    // setIO("input"); 
    scanf("%d%d%d",&n,&m,&s);  
    tot=n; 
    segin::build(1,n,rtin);  
    segout::build(1,n,rtout); 
    for(i=1;i<=m;++i) 
    {
        int l1,r1,l2,r2; 
        scanf("%d%d%d%d",&l1,&r1,&l2,&r2); 
        Add(l1,r1,l2,r2,1);     
        Add(l2,r2,l1,r1,1);     
    }
    Dijkstra();      
    for(i=1;i<=n;++i) printf("%d\n",d[i]);    
    return 0; 
}

  

posted @ 2019-09-18 14:48  EM-LGH  阅读(163)  评论(0编辑  收藏  举报