Transit Tree Path(最短路 dfs 树上祖先lca)

题目链接http://exam.upc.edu.cn/problem.php?id=6690&csrf=EcC0CWCFiJXhqlMPF05uNnXmE6qlJZvU

多种写法堆优化的dijstra:https://www.cnblogs.com/Renyi-Fan/p/7508098.html

另外比较好的题解:

https://blog.csdn.net/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;
}

猜你喜欢

转载自blog.csdn.net/Z_sea/article/details/81189860
今日推荐