思路:K比较小,暴力预处理K次最短路不必说。问题在于哪种排列是最优的呢?采用全排列暴力,每种顺序按照一个环走一遍。
至于一条路走两遍以及以上的情况,在起点的枚举中会被包括进去。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+100;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
typedef pair<LL,LL>P;///first最短距离,second顶点的编号
struct edge{
LL to,cost;
};
struct SHOP{
LL id,pos;
}shop[10];
bool cmp(SHOP A,SHOP B){
return A.pos<B.pos;
}
vector<edge>g[maxn];
LL vis[maxn];
LL dis[maxn][10];
LL n,m;
void dijkstra(LL st,LL k)
{
LL s=st;///起点是st
dis[s][k]=0;
memset(vis,0,sizeof(vis));///初始化
priority_queue< P, vector<P> , greater<P> >que;
que.push({0,s});
while(!que.empty())
{
P p=que.top();que.pop();
int v=p.second;
if(vis[v]) continue;
vis[v]=1;
for(int i=0;i<g[v].size();i++)
{
edge e=g[v][i];
if(dis[e.to][k]>dis[v][k]+e.cost)
{
dis[e.to][k]=dis[v][k]+e.cost;
que.push({dis[e.to][k],e.to});
}
}
}
}
int main(void)
{
memset(dis,0x3f,sizeof(dis));///初始化
LL n,m,k;n=read();m=read();k=read();
for(LL i=1;i<=k;i++){
shop[i].id=read();
shop[i].pos=i;
}
for(LL i=1;i<=m;i++){
LL u,v,cost;u=read();v=read();cost=read();
g[u].push_back({v,cost});
g[v].push_back({u,cost});
}
for(LL i=1;i<=k;i++){
dijkstra(shop[i].id,shop[i].pos);
}
LL ans=0x3f3f3f3f3f3f3f3f;
for(LL i=1;i<=n;i++){
bool flag=1;
for(LL j=1;j<=k;j++){
if(shop[j].id==i){
flag=0;
}
}
if(flag==0) continue;
do{
LL sum=0;
/// for(LL j=1;j<=k;j++) cout<<shop[j].pos<<" ";
/// cout<<endl;
/// debug(i);
sum+=dis[i][shop[1].pos];
for(LL j=1;j<k;j++){
sum+=dis[shop[j].id][shop[j+1].pos];
}
sum+=dis[i][shop[k].pos];
/// debug(sum);
ans=min(ans,sum);
}while(next_permutation(shop+1,shop+k+1,cmp));
}
cout<<ans<<endl;
return 0;
}