离散化坑死人了 !!! 不排序就lower_bound。。。
用dijkstra跑出每一个点到其它点的距离,注意一定要加入1号点且,有多的1就不用加入。
k = 现在vector 里面的数量
跑k遍dijkstra。 得到一个k * k 的图, 现在的目标就是在这个图中,从1开始,经过每一个点且回到原点的最短距离。 哈密顿回路板子。
可以参考之前写的哈密顿回路。
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int mod = 1000000007;
const int N = 12,M = 4e5+10;
int dp[1<<N][N];
int d[N][N],dis[M];
int e[M],ne[M],h[M],w[M],idx=1;
bool book[M];
int n,m,k;
vector<int> a;
void add(int a,int b,int c){
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int find(int x){//没排序就直接for查找
for(int i=0;i<k;i++)
if(a[i] == x) return i;
}
priority_queue<pii,vector<pii>,greater<pii>> pq;
void dij(int sa){
memset(book,false,sizeof(book));
memset(dis,INF,sizeof(dis));
dis[sa] = 0;
pq.push({0,sa});
while(!pq.empty()){
pii t = pq.top(); pq.pop();
int distance = t.first,u = t.second;
if(book[u]) continue;
book[u]=true;
for(int i=h[u];i;i=ne[i]){
int j=e[i];
if(dis[j] > distance + w[i]){
dis[j]=distance + w[i];
pq.push({dis[j],j});
}
}
}
for(int i=0;i<k;i++) d[find(sa)][find(a[i])] = dis[a[i]];
}
signed main(){
IOS;
#ifdef ddgo
freopen("C:\\Users\\asus\\Desktop\\ddgoin.txt","r",stdin);
#endif
cin>>n>>m>>k;
a.push_back(1);
for(int i=0;i<k;i++){
int p; cin>>p;
if(p != 1) a.push_back(p);
}
for(int i=0;i<m;i++){
int a,b,c; cin>>a>>b>>c;
add(a,b,c); add(b,a,c);
}
k = (int)a.size();
// 跑k遍dijkstra
for(int i=0;i<k;i++) dij(a[i]);
// 求哈密顿回路,状压DP
memset(dp,INF,sizeof(dp));
dp[1][0] = 0;
for(int i=0;i<(1<<k);i++)
for(int j=0;j<k;j++)
if((i>>j)&1){
for(int z=0;z<k;z++)
if(((i-(1<<j))>>z)&1)
dp[i][j] = min(dp[i][j],dp[(i-(1<<j))][z]+d[z][j]);
}
int mi = 1e18;
for(int i=0;i<k;i++) mi = min(mi,dp[(1<<k)-1][i]+d[i][0]);
cout<<mi<<endl;
return 0;
}