• Codeforces 786B. Legacy 线段树+spfa


    题目大意:

    给定一个(n)的点的图。求(s)到所有点的最短路
    边的给定方式有三种:

    • (u o v)
    • (u o [l,r])
    • ([l,r] o v)
      (q)为给定边的次数,有(n,q leq 10^5)

    题解

    类比于线段树优化网络流建图
    写一个线段树优化最短路建图即可。

    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
        x=0;char ch;bool flag = false;
        while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
        while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    #define rg register int
    #define rep(i,a,b) for(rg i=(a);i<=(b);++i)
    #define per(i,a,b) for(rg i=(a);i>=(b);--i)
    const int maxn = 100010;
    struct Edge{
        int to,dis;
        Edge(){}
        Edge(const int &a,const int &b){
    		to = a;dis = b;
        }
    };
    vector<Edge>ve[maxn*10];
    inline void add(int u,int v,int d){
        ve[u].push_back(Edge(v,d));
    }
    int T1[maxn<<2],T2[maxn<<2],nodecnt;
    void build1(int rt,int l,int r){
        T1[rt] = ++ nodecnt;
        if(l == r){
    		add(l,T1[rt],0);
    		return ;
        }
        int mid = l+r >> 1;
        build1(rt<<1,l,mid);
        build1(rt<<1|1,mid+1,r);
        add(T1[rt<<1],T1[rt],0);
        add(T1[rt<<1|1],T1[rt],0);
    }
    void build2(int rt,int l,int r){
        T2[rt] = ++ nodecnt;
        if(l == r){
    		add(T2[rt],l,0);
    		return ;
        }
        int mid = l+r >> 1;
        build2(rt<<1,l,mid);
        build2(rt<<1|1,mid+1,r);
        add(T2[rt],T2[rt<<1],0);
        add(T2[rt],T2[rt<<1|1],0);
    }
    
    int p,val;
    void query1(int rt,int l,int r,int L,int R){
        if(L <= l && r <= R){
    		add(T1[rt],p,val);
    		return ;
        }
        int mid = l+r >> 1;
        if(L <= mid) query1(rt<<1,l,mid,L,R);
        if(R >  mid) query1(rt<<1|1,mid+1,r,L,R);
    }
    void query2(int rt,int l,int r,int L,int R){
        if(L <= l && r <= R){
    		add(p,T2[rt],val);
    		return ;
        }
        int mid = l+r >> 1;
        if(L <= mid) query2(rt<<1,l,mid,L,R);
        if(R >  mid) query2(rt<<1|1,mid+1,r,L,R);
    }
    ll dis[maxn*10];bool inq[maxn*10];
    void spfa(int s){
        memset(dis,0x3f,sizeof dis);
        dis[s] = 0;inq[s] = true;
        queue<int>q;q.push(s);
        while(!q.empty()){
    		int u = q.front();q.pop();
    		for(vector<Edge>::iterator it = ve[u].begin();it != ve[u].end();++ it){
    		    if(dis[it->to] > dis[u] + it->dis){
    				dis[it->to] = dis[u] + it->dis;
    				if(!inq[it->to]){
    				    inq[it->to] = true;
    				    q.push(it->to);
    				}
    		    }
    		}inq[u] = false;
        }
    }
    int main(){
        int n,q,s;read(n);read(q);read(s);
        int t,u,v,l,r;
        nodecnt = n;
        build1(1,1,n);build2(1,1,n);
        while(q--){
    		read(t);
    		if(t == 1){
    		    read(u);read(v);read(val);
    		    add(u,v,val);
    		}else if(t == 2){
    		    read(p);read(l);read(r);read(val);
    		    query2(1,1,n,l,r);
    		}else if(t == 3){
    		    read(p);read(l);read(r);read(val);
    		    query1(1,1,n,l,r);
    		}
        }
        spfa(s);
        rep(i,1,n){
    		if(dis[i] != dis[0]) printf("%lld",dis[i]);
    		else printf("%d",-1);
    		if(i != n) putchar(' ');
    		else putchar('
    ');
        }
        return 0;
    }
    
  • 相关阅读:
    沙雕玩意儿
    1558:聚会 ybt
    沙雕关于线段树的一点总结(滑稽)
    卑微
    沙雕题目 来自luogu
    甜茶好帅啊
    python 中字符串的格式化
    python的几个小程序
    python 第一课
    基于笔画宽度变换的自然场景文本检测方法
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6952386.html
Copyright © 2020-2023  润新知