问题 J: 自由世界(最短路)

问题 J: 自由世界
时间限制: 5 Sec 内存限制: 128 MB

题目描述
牛牛最近在玩某款游戏,其地图不能看成一个平面直角坐标系,而类似于一张无向图。
地图上存在n个小镇,小镇从1到n编号。有m条道路连接两个小镇,每条道路有其长度wi。
牛牛在k个小镇建立了传送门,也就是说,牛牛可以在任何时候任何瞬间不花费任何代价,直接到达这k个小镇的任何一个。
牛牛一开始在小镇1,牛牛想按1到n的顺序访问所有小镇按顺序做任务,问牛牛需要走过的最短长度是多少。
牛牛可以提前到达某个小镇,但是必须做完前一个小镇的任务,才能做下一个小镇的任务。做任务本身不会增加长度。
输入
第一行输入三个整数n,m,k,表示地图上小镇的数目,连接小镇道路的条数和建立了传送门的小镇的个数。
随后m行,其中第i行输入三个整数ui,vi,wi,表示有一条道路连接了小镇ui和小镇vi,长度为wi。
随后一行输入k个整数,表示建立了传送门的小镇编号。
输出
一行一个整数表示答案。
样例输入 Copy
5 6 1
1 4 9
1 3 66
3 2 27
4 2 10
2 5 62
3 5 92
3
样例输出 Copy
128
提示
样例解释:牛牛一开始在小镇 1,完成任务后,步行至小镇 4,随后步行至小镇 2,共计长度 9+10=19。
完成任务后,传送至小镇 3。
从小镇 3 完成任务后,步行至小镇 2,再步行至小镇 4,这里长度为 27+10=37,共计长度为 37+19=56。
然后从小镇 4 完成任务后步行至小镇 2, 然后步行至小镇 5,这里长度为10+62=72,共计长度为 56+72=128。
共计长度为 128。

对于10%的数据有n≤3,k=0。
对于30%的数据有k=0。
另有30%的数据有m=n-1。
对于60%的数据有n≤300。
对于100%的数据有1≤n≤2000,n−1≤m≤5000,0≤k≤n,1≤ui,vi≤n,1≤wi≤1000。
数据保证给定的小镇两两相互可达。
注意,连接某两个小镇的可能有多条道路,也有可能有道路的两端是同一个小镇。

思路:

思路类似上一篇博客
只需要把代价换成最短路就好了,对于每个点跑一次最短路。
每次求最短路时,都要把传送门放入队列。

代码:


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PLL;
typedef pair<int, int>PII;
typedef pair<double, double>PDD;
#define I_int ll
inline ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
#define read read()
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
ll ksm(ll a, ll b, ll p)
{
    ll res = 1;
    while(b)
    {
        if(b & 1)res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
const int inf = 0x3f3f3f3f;
#define PI acos(-1)
const int maxn=1e5+100;

int n,m,k;
int h[maxn],idx;
struct node{
    int e,ne,w;
}edge[maxn];
int a[maxn],vis[maxn];

void add(int u,int v,int w){
    edge[++idx]={v,h[u],w};
    h[u]=idx;
}

int st[maxn],dis[maxn];

void bfs(int s){
    queue<int>q;
    memset(dis,0x3f,sizeof dis);
    memset(st,0,sizeof st);
    st[s]=1;dis[s]=0;q.push(s);
    rep(i,1,k){
        int x=a[i];st[x]=1;dis[x]=0;q.push(x);
    }
    while(!q.empty()){
        int t=q.front();q.pop();st[t]=0;
        for(int i=h[t];i!=0;i=edge[i].ne){
            int j=edge[i].e;
            if(dis[j]>dis[t]+edge[i].w){
                dis[j]=dis[t]+edge[i].w;
                if(!st[j]){
                    st[j]=1;q.push(j);
                }
            }
        }
    }
}

int main()
{

    n=read,m=read,k=read;
    rep(i,1,m){
        int u=read,v=read,w=read;
        add(u,v,w);add(v,u,w);
    }
    rep(i,1,k){
        a[i]=read;
        vis[a[i]]=1;
    }
    int res=0;
    rep(i,2,n){
        if(vis[i]) continue;
        bfs(i-1);
        res+=dis[i];
    }
    cout<<res<<endl;
    return 0;
}

/*

**/

posted @ 2021-06-12 09:16  OvO1  阅读(102)  评论(0编辑  收藏  举报