Codeforces 786B - Legacy 最短路 and 线段树

题意:

1.求S到所有点的最短路

2.三种加有向边的方式

(1)点->点(2)点到区间(3)区间到点

解:

1、暴力的话边加不完,

2、区间操作-->考虑线段树

3、建立两棵线段树  

入树和出树 

void build(ll &x,ll l,ll r,ll op){
    x=++tot;
    if(l==r){
            if(op==0){
                ind_0[l]=x;
            }else{
                ind_1[l]=x;add(ind_0[l],ind_1[l],0);add(ind_1[l],ind_0[l],0);
            }
            return ;
    }
    ll mid=(l+r)>>1;
    build(ls[x],l,mid,op);build(rs[x],mid+1,r,op);
    if(!op){
        add(ls[x],x,0);add(rs[x],x,0);
    }else{
        add(x,ls[x],0);add(x,rs[x],0);
    }
}

(1)*****注意出树的叶子节点要和出树对应的叶子节点 要将无向边缩成一个点*****

(2)***边的数量要足够*****

(3)最后求的就是出树的叶子节点的dis值

加边:

1:u->v,加边<A的叶子节点u,B的叶子节点v,w><A的叶子节点u,B的叶子节点v,w>

2:u->[l,r],加边<A的叶子节点u,{B树中[l,r]区间对应的节点集合},w><A的叶子节点u,{B树中[l,r]区间对应的节点集合},w>

3:[l,r]->v,加边<{A树中[l,r]区间对应的节点集合},B树的叶子节点v,w>

[1]

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<queue>
#define en '\n'
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll maxn=8*(100000+10);
ll n,Q,s;
ll ls[maxn],rs[maxn],ind_0[maxn],ind_1[maxn];
ll cnt=0;
ll rt[10];
ll head[maxn];
ll read(){
ll tem;scanf("%I64d",&tem);return tem;
}
struct node{
ll v,nxt,w;
}edge[maxn<<3];
void add(ll x,ll y,ll w){
    edge[++cnt]=(node){y,head[x],w};head[x]=cnt;
}
void padd(ll x,ll l,ll r,ll ql,ll qr,ll goal ,ll op,ll w){
    if(l>=ql and r<=qr){
        if(!op){
            add(x,goal,w);
        }
        else add(goal,x,w);
        return ;
    }
    ll mid=(l+r)>>1;
    if(ql<=mid){
        padd(ls[x],l,mid,ql,qr,goal,op,w);
    }
    if(qr>mid){
        padd(rs[x],mid+1,r,ql,qr,goal,op,w);
    }
}
ll tot=0;
void build(ll &x,ll l,ll r,ll op){
    x=++tot;
    if(l==r){
            if(op==0){
                ind_0[l]=x;
            }else{
                ind_1[l]=x;add(ind_0[l],ind_1[l],0);add(ind_1[l],ind_0[l],0);
            }
            return ;
    }
    ll mid=(l+r)>>1;
    build(ls[x],l,mid,op);build(rs[x],mid+1,r,op);
    if(!op){
        add(ls[x],x,0);add(rs[x],x,0);
    }else{
        add(x,ls[x],0);add(x,rs[x],0);
    }
}
priority_queue< pair<ll,ll> >q;
bool vis[maxn];
ll dis[maxn];
void dj(){
    mem(dis,0x3f);dis[ind_0[s]]=0;q.push({0,ind_0[s]});
    while(q.size()){
        ll now=q.top().second;q.pop();if(vis[now])continue;vis[now]=1;
        for(ll i=head[now];i;i=edge[i].nxt){
            ll y=edge[i].v;
            if(dis[y]>dis[now]+edge[i].w){
                dis[y]=dis[now]+edge[i].w;
                q.push({-dis[y],y});
            }
        }
    }
}
signed main()
{
    #ifdef local
    freopen("input2.txt","r",stdin);
    #endif
    cin>>n>>Q>>s;
    cnt=0;
    build(rt[0],1,n,0);build(rt[1],1,n,1);
    while(Q--){
        ll f,x,y,w;f=read();
        if(f==1){
            x=read(),y=read(),w=read();
            add(ind_0[x],ind_1[y],w);
        }
        else if(f==2){
            ll now=read();
            x=read(),y=read(),w=read();
            add(ind_0[now],++tot,w);
            padd(rt[1],1,n,x,y,tot,1,0);
        }
        else{
            ll now=read();
            x=read(),y=read(),w=read();
            padd(rt[0],1,n,x,y,++tot,0,0);add(tot,ind_1[now],w);
        }
    }
    dj();
    for(ll i=1;i<=n;i++){
        if(dis[ind_1[i]]==inf){
            cout<<-1<<' ';
        }else
        cout<<dis[ind_1[i]]<<' ';
    }
    return 0;
}

参考:[1]Blackops  CF 787D Legacy(线段树思想构图+最短路)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值