【2022 杭电多校】第五场 1003 【建图+Dijkstra】

链接

https://acm.hdu.edu.cn/showproblem.php?pid=7187

思路

先建树,求出每个点的层数
可以给每一层新建一个点,相同层数的和这个点距离为0,层间距离为k的点(+k、-k)边权为p
然后跑Dijkstra求最短路
注意新建的边只能建单向的,因为如果建了双向,相同层的点距离都是0;单向边方向满足从一个点出发能回到这个点

code

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 4000005,M = 4000005;
using namespace std;
int n,m,s,t,k,p;
bool ok[N];
int head[M],cnt;
ll dis[N];
struct edge{
	int v,next,to;
};
edge e[M];  //边的数量 
struct node{
	ll dis;
	int pos;
	bool operator < (const node &x) const{
		return x.dis<dis;
	}
};
priority_queue<node>pq;

int dep[N],maxdep;
bool vis[N];

inline void add(int u,int v,int d){
	cnt++;
	e[cnt].to=v;
	e[cnt].v=d;
	e[cnt].next=head[u];
	head[u]=cnt;
}

void dijk(){
	dis[s]=0;
	pq.push((node){0,s});
	while(!pq.empty()){
		node tem=pq.top();
		pq.pop();
		int x=tem.pos,d=tem.dis;
		if(ok[x]){
			continue;
		}
		ok[x]=1;
		for(int i=head[x];~i;i=e[i].next){
			int y=e[i].to;
			if(dis[y]>dis[x]+e[i].v){
				dis[y]=dis[x]+e[i].v;
				if(!ok[y]){
					pq.push((node){dis[y],y});
				}
			}
		}
	}
}

void dfs(int now,int fa){
    dep[now]=dep[fa]+1;
    maxdep=max(maxdep,dep[now]);
    for(int i=head[now];~i;i=e[i].next){
        int x=e[i].to;
        if(!vis[x]){
            vis[x]=1;
            dfs(x,now);
        }
    }
}

int main(){
    int T;cin>>T;
    while(T--){
        cnt=0;
        maxdep=0;
        scanf("%d",&n);
        for(int i=1;i<=3*n;i++){
            head[i]=-1;
            dis[i]=1e18;
            vis[i]=0;
            ok[i]=0;
        }
        for(int i=1,u,v,w;i<n;i++){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        dep[0]=0; vis[0]=1; vis[1]=1;
        dfs(1,0);
        scanf("%d%d",&k,&p);

        for(int i=1;i<=n;i++){
           add(i,n+dep[i],0);
            if(dep[i]>k){
               add(n+dep[i]-k,i,p);
            }
            if(dep[i]+k<=maxdep){
               add(n+dep[i]+k,i,p);
            }
        }

        scanf("%d%d",&s,&t);
        dijk();
        printf("%lld\n",dis[t]);
    }
    system("pause");
    return 0;
}
posted @   starlightlmy  阅读(73)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示