zoukankan      html  css  js  c++  java
  • BUAA 1301 最短路

    一棵n个点的有根树,以1号点为根,走一条边需要花费相应的代价,任意深度相差为1的点之间可以相互跳跃,花费代价为p,求s走到t的最小代价。

    1<=T<=20,1<=n<=$10^{5}$,1<=s,t,u,v<=n,0<=p,w<=$10^{9}$

    题解

    一开始题没理解清楚同时没模拟样例,以为只要让边权和p比较一下取个小的,然后边权下放到子节点,求个前缀和和lca就行,然后复习了半天倍增样例都没过。

    仔细看了一下题,任意深度相差一可跳,好家伙。理所应当想到最短路,相邻两层的点建边,但是边的数量级直接变成$n^{2}$。

    搜了下题解,果然要技巧。

    在层之间设置新的点,用于连接两层

    好!又没看清,只建了一个点还是双向边,提交上去就WA了。

    再一看,要两个“中转点”,因为只有一个的话必然是双向边,那么同层的点就可能跳跃。

    我记得之前做过类似的题。

    #include<iostream>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    using namespace std;
    
    #define ll long long
    const int maxn=100005;
    int T,n,p,s,t;
    int cnt,max_dep,fa[maxn],dep[maxn],head[maxn*3];
    struct edge{
        int x,y,val,next;
    }e[maxn<<3];
    
    template<class T>inline void read(T &x){
        x=0;int f=0;char ch=getchar();
        while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x = f ? -x : x ;
    }
    
    ll max(ll a,ll b){return a>=b ? a : b ;}
    ll min(ll a,ll b){return a<=b ? a : b ;}
    
    void add(int x,int y,int val){
        e[++cnt]={x,y,val,head[x]};
        head[x]=cnt;
    }
    
    void dfs(int x){
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y;
            if(y==fa[x]) continue;
            fa[y]=x;
            dep[y]=dep[x]+1;
            dfs(y);
        }
    }
    
    bool vis[maxn*3];
    ll d[maxn*3];
    
    void dijkstra(){
        priority_queue<pair<ll,int> > q ;
        memset(d,0x3f,sizeof(d));
        memset(vis,false,sizeof(vis));
        //printf("%lld
    ",d[1]*2);
        d[s]=0;
        q.push(make_pair(0,s));
        while(!q.empty()){
            int x=q.top().second;
            q.pop();
            if(vis[x]) continue;
            vis[x]=true;
            for(int i=head[x];i;i=e[i].next){
                int y=e[i].y,val=e[i].val;
                if(d[y]>d[x]+val){
                    d[y]=d[x]+val;
                    q.push(make_pair(-d[y],y));
                }
            }
        }
    }
    
    void work(int cas){
        read(n),read(p),read(s),read(t);
        cnt=max_dep=0;
        memset(head,0,sizeof(head));
        for(int i=1;i<=n;i++) fa[i]=0;
        for(int i=1;i<n;i++){
            int x,y,val;
            read(x),read(y),read(val);
            val=min(val,p);
            add(x,y,val),add(y,x,val);
        }
        dep[1]=1;
        dfs(1);
        for(int i=1;i<=n;i++) max_dep=max(max_dep,dep[i]);
        for(int i=1;i<n;i++) add(i,n+dep[i],0),add(n+max_dep+dep[i],i,p);
        for(int i=2;i<=n;i++) add(i,n+max_dep+dep[i]-1,0),add(n+dep[i]-1,i,p);
        /*每层之间加入中转点实现跳跃
          但是需每层之间加入两个且建立单向边,不然会导致同层跳跃
          只用指定指出或者指入的边边权为p即可
        */
        dijkstra();
        printf("Case #%d: %lld
    ",cas,d[t]);
    }
    
    int main(){
        read(T);
        for(int i=1;i<=T;i++) work(i);
        return 0;
    }
    最短路
  • 相关阅读:
    Keras学习率调整
    机器学习算法的调试---梯度检验(Gradient Checking)
    Python 上下文管理器
    Python垃圾回收机制
    Css 动画的回调
    全新的membership框架Asp.net Identity——绕不过的Claims
    CSS代码重构与优化
    html5 本地存储
    ASP.NET MVC 随想录
    谈谈Angular关于$watch,$apply 以及 $digest的工作原理
  • 原文地址:https://www.cnblogs.com/sto324/p/15302496.html
Copyright © 2011-2022 走看看