线段树优化最短路建边

Legacy
给出一个带权有向图,有三种操作:

1.u->v添加一条权值为w的边

2.区间[l,r]->v添加权值为w的边

3.v->区间[l,r]添加权值为w的边

求st点到每个点的最短路

#include 
#include 
#include 
#include 
#include 
#include 
#define File(x) "test."#x
#define For(i,s,e) for(int i=(s); i<=(e); i++)
#define Rep(i,s,e) for(int i=(s); i>=(e); i--)
#define LSON o<<1, l, mid
#define RSON o<<1|1, mid+1, r
using namespace std;

const int N=1000000+1;
typedef long long LL;
struct Node{
    int x;
    LL w;
    bool operator < (const Node & o) const {
        return w>o.w;
    }
};

int q,n,s,maxo;
vectorv[N];

void addEdge(int x, int y, LL w){
    v[x].push_back((Node){y,w});
}
void build_p_seg(int o, int l, int r){//点到区间 
    maxo=max(maxo, o);
    if(l==r){
        addEdge(o+n, l, 0);//
        return;
    }
    int mid=(l+r)>>1;
    build_p_seg(LSON); build_p_seg(RSON);
    addEdge(o+n, (o<<1)+n, 0); addEdge(o+n, (o<<1|1)+n, 0);//
}
void build_seg_p(int o, int l, int r){
    if(l==r){
        addEdge(l, o+n+maxo, 0);//
        return;
    }
    int mid=(l+r)>>1;
    build_seg_p(LSON); build_seg_p(RSON);
    addEdge((o<<1)+maxo+n, o+maxo+n, 0); addEdge((o<<1|1)+maxo+n, o+maxo+n, 0);//
}
void add_p_seg(int x, LL w, int L, int R, int o, int l, int r){
    if(L<=l && r<=R){
        addEdge(x, o+n, w); return;
    }
    int mid=(l+r)>>1;
    if(L<=mid) add_p_seg(x, w, L, R, LSON);
    if(R>mid) add_p_seg(x, w, L, R, RSON);
}
void add_seg_p(int x, LL w, int L, int R, int o, int l, int r){
    if(L<=l && r<=R){
        addEdge(o+maxo+n, x, w); return;
    }
    int mid=(l+r)>>1;
    if(L<=mid) add_seg_p(x, w, L, R, LSON);
    if(R>mid) add_seg_p(x, w, L, R, RSON);
}

LL dis[N],inf=5000000000LL*500000;
bool used[N];

void dij(){
    priority_queueq;
    For(i,1,n+2*maxo) dis[i]=inf;
    dis[s]=0; q.push((Node){s,0});

    while(!q.empty()){
        int x=q.top().x; q.pop();
        if(used[x]) continue;
        used[x]=1;

        if(!v[x].empty())
        for(int p=0; pint u=point.x;
            if(dis[u]>dis[x]+point.w){
                dis[u]=dis[x]+point.w;
                q.push((Node){u,dis[u]});
            }
        } 
    }
}

int main()
{
    freopen(File(in),"r",stdin);
    freopen(File(out),"w",stdout);

//  ios::sync_with_stdio(false);

    scanf("%d%d%d",&n,&q,&s);
    build_p_seg(1,1,n);
    build_seg_p(1,1,n);
    while(q--){
        int opt,x,y,l,r;
        LL w;
        scanf("%d",&opt);
        if(opt==1){
            scanf("%d%d%lld",&x,&y,&w);
            if(x!=y) addEdge(x,y,w);
        } 
        else if(opt==2){
            scanf("%d%d%d%lld",&x,&l,&r,&w);
            add_p_seg(x,w,l,r,1,1,n);
        }
        else{
            scanf("%d%d%d%lld",&x,&l,&r,&w);
            add_seg_p(x,w,l,r,1,1,n);
        }
    }
    dij();
    For(i,1,n) printf("%lld ",dis[i]==inf?-1:dis[i]);
    puts("");

    return 0;
}

你可能感兴趣的:(线段树,最短路)