【GXOI/GZOI2019】旅行者

题面

 https://www.luogu.org/problem/P5304

题解

// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#define ri register int
#define N 100500
#define M 1000500
#define LL long long
#define INF 1000000007LL
using namespace std;

struct node {
  int v; LL dis;
  bool operator < (const node &rhs) const {
    return dis>rhs.dis;
  }
};

int n,m,k;
vector<int> id[N];
int to[M],len[M],cc;
int a[N];
priority_queue<node> pq;

LL dis[N][2],ans;
int fro[N][2];
bool imp[N],vis[N];

void add_egde(int a,int b,int c) {
  id[a].push_back(++cc); to[cc]=b; len[cc]=c;
  id[b].push_back(++cc); to[cc]=a; len[cc]=c;
}

void dij(int opt) {
  for (ri i=1;i<=n;i++) dis[i][opt]=INF*INF,vis[i]=0;
  while (!pq.empty()) pq.pop();
  for (ri i=1;i<=k;i++) {
    dis[a[i]][opt]=0;
    fro[a[i]][opt]=a[i];
    pq.push((node){a[i],dis[a[i]][opt]});
  }
  while (!pq.empty()) {
    int x=pq.top().v; pq.pop();
    if (vis[x]) continue;
    vis[x]=1;
    for (ri i=0,ls=id[x].size();i<ls;i++) {
      int e=id[x][i];
      if (e%2!=opt) continue;
      if (dis[x][opt]+len[e]<dis[to[e]][opt]) {
        dis[to[e]][opt]=dis[x][opt]+len[e];
        fro[to[e]][opt]=fro[x][opt];
        pq.push((node){to[e],dis[to[e]][opt]});
      }
      if (opt) {
        if (dis[x][opt]+len[e]+dis[to[e]][opt^1]<ans && fro[x][opt]!=fro[to[e]][opt^1]) ans=dis[x][opt]+len[e]+dis[to[e]][opt^1];
      }
    }
  }
}

int main(){
  int T,z,y,x;
  scanf("%d",&T);
  while (T--) {
    scanf("%d %d %d",&n,&m,&k);
    for (ri i=1;i<=n;i++) id[i].clear();
    cc=-1;
    for (ri i=1;i<=m;i++) {
      scanf("%d %d %d",&z,&y,&x);
      if (z!=y) add_egde(z,y,x);
    }
    ans=INF*INF;
    memset(imp,0,sizeof(imp));
    for (ri i=1;i<=k;i++) {
      scanf("%d",&a[i]);
      imp[a[i]]=1;
      for (ri j=0,ls=id[a[i]].size();j<ls;j++) {
        int e=id[a[i]][j];
        if (imp[to[e]] && len[e]<ans) ans=len[e];
      }
    }
    dij(0); dij(1);
    for (ri i=1;i<=n;i++) if (fro[i][0]!=fro[i][1] && dis[i][0]+dis[i][1]<ans) ans=dis[i][0]+dis[i][1];
    printf("%lld\n",ans);
  }
}

猜你喜欢

转载自www.cnblogs.com/shxnb666/p/11278508.html