Codeforces 786B(区间图最短路)

Posted aaddvvaanntteezz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 786B(区间图最短路)相关的知识,希望对你有一定的参考价值。

传送门

题意

给定一张$n$个点的有向图,有三种连边方式
  1. $a->b$,代表$a$向$b$连一条有向边
  2. $a->[l,r]$.代表$a$向区间$[l,r]$的所有点连一条有向边
  3. $[l,r]->a$.代表区间$[l,r]$向$a$的连一条有向边
求点$S$到所有点的最短距离

题解

区间图最短路裸题,建出两颗线段树维护整个区间,一个区间可以用线段树表示为$log(n)$个点,这样就把建图时间压缩成$mlogn$了,然后跑最短路就行了。
查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4e6+5;
const int mod = 1e9+7;
const ll inf = 0x3f3f3f3f3f3f3f3f;
ll qpow(ll a,ll b){ll res=1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
struct graph
{
    int head[maxn],nxt[maxn<<1],to[maxn<<1],w[maxn<<1],sz;
    void init(){memset(head,-1,sizeof(head));}
    graph(){init();}
    void push(int a,int b,int c){nxt[sz]=head[a],to[sz]=b,w[sz]=c,head[a]=sz++;}
    int& operator[](const int a){return to[a];}
}g;
int n,m,s,tot;
struct Segment_tree
{
    int id[maxn];
    void build(int root,int l,int r,bool flag){
        id[root]=++tot;
        if(l==r){
            if(flag)
            g.push(id[root],l,0);
            else g.push(l,id[root],0);
            return ;
        }   
        int mid = l+r>>1;
        build(root<<1,l,mid,flag);
        build(root<<1|1,mid+1,r,flag);
        if(flag){
            g.push(id[root],id[root<<1],0);
            g.push(id[root],id[root<<1|1],0);
        }
        else {
            g.push(id[root<<1],id[root],0);
            g.push(id[root<<1|1],id[root],0);
        }
    }
    void addedge(int root,int l,int r,int ul,int ur,int u,int w,bool flag){//区间连边[ul,ur]->u
        if(l>=ul&&r<=ur){
            if(!flag){
                g.push(id[root],u,w);
            }
            else g.push(u,id[root],w);
            return;
        }
        int mid = l+r>>1;
        if(ul<=mid)addedge(root<<1,l,mid,ul,ur,u,w,flag);
        if(ur>mid)addedge(root<<1|1,mid+1,r,ul,ur,u,w,flag);
    }
}in,out;
ll dist[maxn];
struct node
{
    int x;
    ll cost;
    node(int a,ll b):x(a),cost(b){};
    friend bool operator < (node a,node b){
        return a.cost>b.cost;
    }
};
bool vis[maxn];
void dij()
{
    memset(dist,0x3f,sizeof(dist));
    priority_queue<node>q;
    q.push(node(s,0));
    dist[s]=0;
    while(!q.empty()){
        node now = q.top();
        q.pop();
        if(dist[now.x]<now.cost)continue;
        vis[now.x]=1;
        for(int i = g.head[now.x];~i;i = g.nxt[i]){
            if(vis[g[i]])continue;
            if(dist[g[i]]>dist[now.x]+g.w[i]){
                dist[g[i]]=dist[now.x]+g.w[i];
                q.push(node(g[i],dist[g[i]]));
            }
        }
    }
    for(int i = 1;i <= n;++i){
        if(dist[i]==inf)printf("-1 ");
        else printf("%lld ",dist[i]);
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("simple.in", "r", stdin);
    freopen("simple.out", "w", stdout);
#endif
    int type,v,l,r,u,c;
    scanf("%d%d%d",&n,&m,&s);
    tot=n;
    in.build(1,1,n,1);
    out.build(1,1,n,0);
    for(int i = 1;i <= m;++i){
        scanf("%d",&type);
        if(type==1){
            scanf("%d%d%d",&v,&u,&c);
            g.push(v,u,c);
            in.addedge(1,1,n,u,u,v,c,1);
        }
        else if(type==2){
            scanf("%d%d%d%d",&v,&l,&r,&c);
            in.addedge(1,1,n,l,r,v,c,1);
        }
        else {
            scanf("%d%d%d%d",&v,&l,&r,&c);
            out.addedge(1,1,n,l,r,v,c,0);
        }
    }
    dij();
    return 0;
}

以上是关于Codeforces 786B(区间图最短路)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 786B - Legacy(线段树优化建图)

786B - Legacy(线段树 + 最短路)线段树优化建图

codeforces786B Legacy 线段树优化建图

Educational Codeforces Round 102 E. Minimum Path(分层图最短路)

Educational Codeforces Round 102 E. Minimum Path(分层图最短路)

CodeForces - 1486E Paired Payment(分层图最短路)