Dijkstra算法 Atcoder-070-D

题意:

给你一棵无向树,然后给你一个点K,q个查询,每个查询一个x一个y,问从x到y经过k的最短路径


题目链接:点击打开链接

其实这个就是一个单源最短路的问题,以k为单源点,求k到每个点的最短距离,d[i],然后,从x到y的最短路径就是d[x]+d[y];

这个题目转化一下思维方式就行了


注意点:

这是一个无向树,在构造边的时候要注意,两个方向都要加上

代码如下:

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;
const int MAXN=1e5+50;
const long long INF=1e18;
int n;
int k,p;
long long dis[MAXN];
int vis[MAXN];
struct Edge
{
    int from;
    int to;
    int cost;
    Edge(int a,int b,int c)
    {
        from=a;
        to=b;
        cost=c;
    }
};
vector<Edge> edges;
vector<int> G[MAXN];

void Init()
{
    for(int i=0; i<=n; i++)
        G[i].clear();
    edges.clear();
}
struct Heap
{
    int d,u;
    Heap(int a,int b)
    {
        d=a,u=b;
    }
    bool operator<(Heap h)const
    {
        return d>h.d;
    }
};
void Dijkstra(int s)
{
    priority_queue<Heap> p;
    p.push(Heap(0,s));
    for(int i=0; i<=n; i++) dis[i]=INF;
    dis[s]=0;
    memset(vis,0,sizeof(vis));
    while(!p.empty())
    {
        Heap h=p.top();
        p.pop();
        int  u=h.u;
        if(vis[u]) continue;
        for(int i=0; i<G[u].size(); i++)
        {
            Edge &e=edges[G[u][i]];
            if(vis[e.to]) continue;
            if(dis[e.to]>dis[u]+e.cost)
            {
                dis[e.to]=dis[u]+e.cost;
                p.push(Heap(dis[e.to],e.to));
            }
        }
    }
}
int main()
{
    scanf("%d",&n);
    Init();
    for(int i=0; i<n-1; i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        edges.push_back(Edge(x,y,z));
        G[x].push_back(2*i);//无向边,两个方向加
        edges.push_back(Edge(y,x,z));
        G[y].push_back(2*i+1);
    }
    scanf("%d%d",&p,&k);
    Dijkstra(k);
    //for(int i=0;i<=n;i++)
    //    cout<<dis[i]<<" ";
    //  cout<<endl;
    for(int i=0; i<p; i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        cout<<dis[x]+dis[y]<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值