系兄弟就来砍我 有向图单源最短路

系兄弟就来砍我

时间限制: 1 Sec  内存限制: 128 MB

题目描述

渣渣灰因为一句“大家好,我系渣渣辉,系兄弟就来砍我”引得众粉丝纷纷拿两米长的大刀寻找。

现有n个据点,编号(1~n),有m条单向路使据点相连。每个据点仅有一个人。

这n个人中有k个粉丝。其中渣渣灰在s据点处。请问这k个粉丝到渣渣灰的最短距离是多少

输入

首行输入nmks。(k<=n<=100m<=500)s为渣渣灰所在位置

接下来m行,每行输入xyz,表示从x到y的距离是z,由于是单向边,则y到x的距离不一定是z。

接下来k个数字,表示粉丝所在据点。

输出

对于每一个粉丝,输出对应的最短距离。

样例输入

3 3 2 1
1 2 1
2 3 1
3 1 1
2 3

样例输出

2 1

提示

数据保证k个粉丝均能到达渣渣灰的据点

分析:

Dijkstra算法求单源最短路裸题,因为要求k个粉丝(起点)到 S 终点的最短距离,如果正向建边,求k次最短路会超时

所以考虑逆向建边,求S点到所有点的最短距离,储存在dis数组中

既然要求k个点到s点的最短路,我们可以反过来求s到这k个点的最短路。这样就变成了单源最短路问题,dijkstra算法和spfa算法都可以做。由于图为有向图,我们在存图时反向存图即可,原本a[i][j]表示i->j,我们可以将它重新定义为j->i,或者存图时直接写成a[j][i]即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 107;
const int inf = 0x3f3f3f3f; //需将road及dis初始化为正无穷inf
int n,m,k,s;
int dis[maxn];  //储存各个点到源点的最短距离,dis[s]为0
int road[maxn][maxn];   //两点之间直接距离关系
bool vis[maxn];     //判断源点到该点的距离是否为最短距离
int fans[maxn];     //粉丝
void dijkstra(int s)
{
    memset(vis, false, sizeof(vis));//标记是否求出最短路径
    vis[s] = true;//标记起点到这一点的最小距离已经求出
    for(int i = 1; i <= n; i++)
        dis[i] = road[s][i];//初始化起点到每一个点的距离

    for(int u = 1; u<n; u++)
    {
        int minD = inf,k = -1;
        for(int i = 1; i<= n; i++)
        {
            if(!vis[i]&&dis[i]<minD)
            {
                k = i;//记录下标
                minD = dis[i];//记录最小值
            }
        }
        vis[k] = true;//标记已经访问过
        //松弛操作
        for(int i = 1; i<= n; i++)
        {
            if(!vis[i]&&dis[k]+road[k][i]<dis[i])
            {
                dis[i]=dis[k]+road[k][i];
            }//if
        }//for
    }
}
int main()
{
    while(scanf("%d%d%d%d",&n,&m,&k,&s)!=EOF){
        memset(road,inf,sizeof(road));
        for(int i=1;i<=m;i++)
        {
            int a,b,d;
            scanf("%d%d%d",&a,&b,&d);
            road[b][a]=min(d,road[b][a]);//逆向建边
        //起点是fans[i],终点是S
        }

        for(int i=1;i<=k;i++)
        scanf("%d",&fans[i]);
        dis[s]=0;

        dijkstra(s);
        for(int i=1;i<=k;i++)
        {
            printf("%d",dis[fans[i]]);
            if(i==k)    printf("\n");
            else    printf(" ");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/81228973