问题 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;
}
/*
**/