题目链接http://exam.upc.edu.cn/problem.php?id=6690&csrf=EcC0CWCFiJXhqlMPF05uNnXmE6qlJZvU
多种写法堆优化的dijstra:https://www.cnblogs.com/Renyi-Fan/p/7508098.html
另外比较好的题解:
https://blog.youkuaiyun.com/algzjh/article/details/77132374
https://www.cnblogs.com/muziyari/p/7612408.html
小弟其中的一个做法:Dijstra
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline void read(ll &t){ //输入挂
ll f=1,ans=0;
char c;
for(c=getchar();!isdigit(c);c=getchar()){
if(c=='-') f=-1;
}for( ;isdigit(c);c=getchar()){
ans=ans*10+c-'0';
}
t = f*ans;
}
typedef struct Edge{
ll to,next,w;
}Edge;
Edge e[300005];
typedef pair<ll,ll>P;
ll head[300005];
ll dis[300005];
ll cnt=0;
void add_edge(ll u,ll v,ll w){
e[cnt].to=v; //终点为V
e[cnt].next=head[u]; //保存上一条边的位置
e[cnt].w=w; //记录边的权值
head[u]=cnt++; //不断更换e[]的下标
}
typedef struct Rule{
bool operator ()(const ll &a,const ll &b)const {
return dis[a]>dis[b]; //把目前众多点中最小的放到堆顶
}
}cmp;
void dijstra(ll k){
memset(dis,127,sizeof(dis)); //127是最大值
priority_queue< ll , vector<ll> , Rule > q; //定义优先队列
dis[k]=0; //k、点位置0
q.push(k); //放K点进去
while(!q.empty()){
ll u=q.top();
q.pop();
for(ll i=head[u];~i;i=e[i].next){ //拿顶点u的边出来
ll v=e[i].to; //终点暂存
if(dis[v]>dis[u]+e[i].w){ //满足更新条件
dis[v]=dis[u]+e[i].w; //更新
q.push(v); //放点进堆
}
}
}
}
int main()
{
ll n,u,v,w,Q,k,a,b,ans;
memset(head,-1,sizeof(head)); //记得要初始化
read(n);
for(ll i=1;i<n;i++){
read(u),read(v),read(w);
add_edge(u,v,w); // 要是有相图就只要一条
add_edge(v,u,w); // 要是无向图不要忘了这一句
}
read(Q),read(k);
dijstra(k); //在某一点进行松弛
for(ll i=0;i<Q;i++){
read(a),read(b);
ans=dis[a]+dis[b]; //以k为根节点,dis[a],dis[b]为直径
printf("%lld\n",ans);
}
return 0;
}