仔细看题目发现需要访问的点一共只有5个,那么即使做5遍最短路复杂度也不超时!!! 做五遍最短路后得出每个亲戚到不同亲戚间的最短距离。
这道题的拜访顺序是不固定的,也就是我们要在不同的拜访顺序中找到最小的那一条路线。
我们可以全排列出不同的路线,最后按照一个顺序求出每个路线的距离,最后求最小即可。
#include <bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f
using namespace std;
typedef pair<int,string> PII;
const int N=1e5+10;//注意边的范围,由于我们重新构图 500*500最坏
int n,m,k,ans,ecnt;
int head[N],vis[N];
int d[N],a[6];
int g[6][N];
struct edge {
int u,v,next,w;
} E[N<<1];
void add(int u,int v,int w) {
E[++ecnt].u=u;
E[ecnt].v=v;
E[ecnt].w=w;
E[ecnt].next=head[u];
head[u]=ecnt;
}
//跑一遍spfa
void spfa(int u) {//传入下标
memset(d,INF,sizeof d);
memset(vis,0,sizeof vis);
vis[a[u]]=1;
d[a[u]]=0;
queue<int> q;
q.push(a[u]);
while(!q.empty()) {
int t=q.front();
q.pop();
vis[t]=0;
for(int i=head[t]; i; i=E[i].next) {
int v=E[i].v;
if(d[v]>d[t]+E[i].w) {
d[v]=d[t]+E[i].w;
if(!vis[v]) {
vis[v]=1;
q.push(v);
}
}
}
}
for(int i=1; i<=n; i++) {
g[u][i]=d[i];
}
}
int s[6];//记录i号节点前一个节点是谁
void dfs(int x,int d) {//全排列
if(d==6) {
s[d]=x;
int sum=0;
for(int i=1; i<6; i++) {
sum+=g[s[i]][a[s[i+1]]];//注意二维是a不是下标
}
ans=min(sum,ans);
return ;
}
for(int i=1; i<6; i++) {
if(!vis[i]) {
vis[i]=1;
s[d]=x;
dfs(i,d+1);
s[d]=0;
vis[i]=0;
}
}
}
int main() {
cin>>n>>m;
a[0]=1;
for(int i=1; i<6; i++) {
cin>>a[i];
}
for(int i=1; i<=m; i++) {
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
for(int i=0; i<6; i++) {
spfa(i);
}
ans=INF;
dfs(0,1);
cout<<ans<<endl;
return 0;
}