HDU 5669 Road(线段树建树)(分层图最短路)

Posted 贱人方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5669 Road(线段树建树)(分层图最短路)相关的知识,希望对你有一定的参考价值。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5669

【分析】线段树建树+分层图最短路

 

#include <cstdio>
#include <map>
#include <algorithm>
#include <vector>
#include <iostream>
#include <set>
#include <queue>
#include <string>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
typedef pair<int,int>pii;
typedef long long LL;
const int N=6e5+5;
const int mod=1e9+7;
int n,m,s,k,t,cnt,idl[N<<1],idr[N<<1];
bool vis[N][11];
LL d[N][11];
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;
    int c;
    LL w;
    bool operator<(const man &e)const{
        return w>e.w;
    }
};
priority_queue<man>q;
void dij(int s){
    memset(d,-1,sizeof d);memset(vis,0,sizeof vis);
    d[s][0]=0;
    q.push(man{s,0,0});
    while(!q.empty()){
        int u=q.top().v,c=q.top().c;q.pop();
        if(vis[u][c])continue;
        vis[u][c]=1;
        for(int i=0;i<edg[u].size();++i){
            int v=edg[u][i].first,w=edg[u][i].second;
            if(!vis[v][c]&&(d[v][c]==-1||d[v][c]>d[u][c]+w)){
                d[v][c]=d[u][c]+w;
                q.push(man{v,c,d[v][c]});
            }
            if(c<k){
                if(!vis[v][c+1]&&(d[v][c+1]==-1||d[v][c+1]>d[u][c])){
                    d[v][c+1]=d[u][c];
                    q.push(man{v,c+1,d[v][c+1]});
                }
            }
        }
    }
}
int main()
{
    int x,y,w,l,r;
    int T;
    scanf("%d",&T);
    while(T--){
        for(int i=0;i<N;i++)edg[i].clear();
        scanf("%d%d%d",&n,&m,&k);
        cnt=n;
        buildl(1,1,n);
        buildr(1,1,n);
        pre(1,1,n);
        while(m--)
        {
            ++cnt;
            scanf("%d%d%d%d%d",&x,&y,&l,&r,&w);
            addl(1,1,n,x,y,w);
            addr(1,1,n,l,r);
            cnt++;           //此处要注意
            addl(1,1,n,l,r,w);
            addr(1,1,n,x,y);
        }
        dij(1);
        LL ans=1000000000000;
        for(int i=0;i<=k;i++)ans=min(ans,d[n][i]);
        if(ans!=-1)printf("%lld\n",ans);
        else puts("CreationAugust is a sb!");
    }
    return 0;
}

 

以上是关于HDU 5669 Road(线段树建树)(分层图最短路)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3499 分层图最短路+Trie树

HDU 5861 Road(线段树 区间修改 单点查询)

HDU 1754线段树基本操作,建树,更新,查询

最短路合集(分层图最短路传递闭包路径还原k短路...)

2016 Multi-University Training Contest 10 [HDU 5861] Road (线段树:区间覆盖+单点最大小)

hdu3966 树链剖分+线段树 裸题