D 自由世界
思路很简单,先给每个点跑一遍最短路,记录到
的路径长度
。再去管传送门,从每个传送门这跑一遍最短路,记录传送门到
的路径
,
和
取个最小值即可。
我一开始为了图个方便,把传送门和每个点都建了个边权为的边,导致凭空多出来至少
条边,就T了,呜呜呜。。。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+10;
const int inf=0x3f3f3f3f;
struct sa{
int dis;
int pos;
};
bool operator <(const sa &a,const sa &b) { return a.dis>b.dis; }
priority_queue<sa>q;
struct Edge
{
int u, v, w, next;
}edge[N<<2];
int head[N];
int cnt;
void add_edge(int u, int v, int w)
{
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
}
int dis[N];
bool vis[N];
int n,m,s,t,u,v,w,T,k;
void dij(int s,int v,int d[]){
memset(vis,0,sizeof(vis));
for (int i=1;i<=n;i++) d[i] = inf;
d[s]=v;
q.push( (sa) {v,s});
while(!q.empty())
{
sa ns=q.top();
q.pop();
int x=ns.pos;
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x]; i!=-1 ; i=edge[i].next)
{
int to=edge[i].v;
int dd=d[x]+edge[i].w;
if(d[to]>dd)
{
d[to]=dd;
q.push( (sa) {d[to],to});
}
}
}
}
int cnt1[N];
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d%d",&n,&m,&k);
for(int i = 1 ;i <= m ;i++){
scanf("%d%d%lld",&u,&v,&w);
add_edge(u, v, w);
add_edge(v, u, w);
}
for(int i = 1 ;i <= n - 1 ;i++){
dij(i, 0, dis);
cnt1[i + 1] = dis[i + 1];
}
for(int i = 1 ;i <= k; i++){
scanf("%d",&u);
dij(u , 0 , dis);
for(int j = 1 ;j <= n - 1; j++){
cnt1[j + 1] = min( cnt1[j + 1] , dis[j + 1]);
}
}
long long ans = 0;
for (int i = 2; i <= n; i++) {
ans += cnt1[i];
}
printf("%lld",ans);
return 0;
} 
京公网安备 11010502036488号