codeforces 786B legacy 线段树建图

http://www.cnblogs.com/jianrenfang/p/6622404.html

会长的代码很朴实,很平易近人。就是区间最短路。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

typedef pair<int,int>pii;
typedef long long LL;
const int N=6e6+5;
const int mod=1e9+7;
int n,m,s,cnt,idl[N<<1],idr[N<<1];
bool vis[N];
LL d[N];
vector<pii>edg[N];
void buildl(int rt,int l,int r)//向上走的一棵树
{
    idl[rt]=++cnt;
    if(l==r)return ;
    int m=l+r>>1;
    buildl(rt<<1,l,m);
    buildl(rt<<1|1,m+1,r);
    edg[idl[rt<<1]].push_back(make_pair(idl[rt],0));
    edg[idl[rt<<1|1]].push_back(make_pair(idl[rt],0));
}
void buildr(int rt,int l,int r)//向下走的一棵树
{
    idr[rt]=++cnt;
    if(l==r)return ;
    int m=l+r>>1;
    buildr(rt<<1,l,m);
    buildr(rt<<1|1,m+1,r);
    edg[idr[rt]].push_back(make_pair(idr[rt<<1],0));
    edg[idr[rt]].push_back(make_pair(idr[rt<<1|1],0));
}
void pre(int rt,int l,int r)//连成回路
{
    if(l==r)
    {
        edg[l].push_back(make_pair(idl[rt],0));
        edg[idr[rt]].push_back(make_pair(l,0));
        return;
    }
    int m=l+r>>1;
    pre(rt<<1,l,m);
    pre(rt<<1|1,m+1,r);
}
void addl(int rt,int l,int r,int L,int R,int w)//上走的树连虚点
{
    if(L<=l&&r<=R)
    {
        edg[idl[rt]].push_back(make_pair(cnt,w));
        return;
    }
    int mid=(l+r)/2;
    if(L<=mid)addl(rt*2,l,mid,L,R,w);
    if(R>mid)addl(rt*2+1,mid+1,r,L,R,w);
}
void addr(int rt,int l,int r,int L,int R)//虚点连向下走的树
{
    if(L<=l&&r<=R)
    {
        edg[cnt].push_back(make_pair(idr[rt],0));
        return;
    }
    int mid=(l+r)/2;
    if(L<=mid)addr(rt*2,l,mid,L,R);
    if(R>mid)addr(rt*2+1,mid+1,r,L,R);
}
struct man
{
    int v;
    LL w;
    bool operator<(const man &e)const
    {
        return w>e.w;
    }
};
priority_queue<man>q;
void dij(int s)
{
    for(int i=0; i<=cnt; i++)d[i]=-1,vis[i]=0;
    d[s]=0;
    q.push(man{s,0});
    while(!q.empty())
    {
        int u=q.top().v;
        q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=0; i<edg[u].size(); ++i)
        {
            int v=edg[u][i].first,w=edg[u][i].second;
            if(!vis[v]&&(d[v]==-1||d[v]>d[u]+w))
            {
                d[v]=d[u]+w;
                q.push(man{v,d[v]});
            }
        }
    }
}
int main()
{
    int w;
    scanf("%d%d%d",&n,&m,&s);
    cnt=n;//前n个点预留出来
    buildl(1,1,n);
    buildr(1,1,n);
    pre(1,1,n);
    while(m--)
    {
        ++cnt;//中间一个过渡节点好写
        int op,l,r,x,y;
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d%d",&x,&y,&w);
            addl(1,1,n,x,x,w);
            addr(1,1,n,y,y);
        }
        else if(op==2)
        {
            scanf("%d%d%d%d",&x,&l,&r,&w);
            addl(1,1,n,x,x,w);
            addr(1,1,n,l,r);
        }
        else
        {
            scanf("%d%d%d%d",&x,&l,&r,&w);
            addl(1,1,n,l,r,w);
            addr(1,1,n,x,x);
        }
    }
    dij(s);
    for(int i=1; i<=n; i++)printf("%lld%c",d[i],i==n?'\n':' ');
    return 0;
}

 

posted on 2017-05-05 14:25  very_czy  阅读(211)  评论(0编辑  收藏  举报

导航