斯坦纳树+子集DP
spfa 9272ms
Dijkstra 13016ms
luogu Dijkstra 直接TLE
综上所述斯坦纳树直接spfa
#include<cstdio>
#include<algorithm>
using namespace std;
int Num,cnt,n,m,p,F[1005][2005],stack[1000005],instack[1005],last[1005],sta[15],cost[2005],G[2005],c[15];
struct node1{
int c,id;
}q[15];
struct node{
int to,next,val;
}e[6005];
void add(int a,int b,int c){
e[++cnt].to=b;
e[cnt].next=last[a];
e[cnt].val=c;
last[a]=cnt;
}
void dfs(int t,int x,int y){
if (t>Num){
G[x]=cost[y];
return;
}
dfs(t+1,x<<1,y);
dfs(t+1,x<<1|1,y|sta[t]);
}
int main(){
scanf("%d%d%d",&n,&m,&p);
for (int i=1; i<=m; i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
for (int i=0; i<p; i++) scanf("%d%d",&q[i].c,&q[i].id);
for (int st=1; st<=n; st++)
for (int i=0; i<(1<<p); i++)
F[st][i]=1e9;
for (int i=0; i<p; i++) F[q[i].id][1<<i]=0;
for (int i=1; i<=n; i++) F[i][0]=0;
for (int i=0; i<(1<<p); i++){
for (int st=1; st<=n; st++)
for (int j=i; j; j=(j-1)&i)
F[st][i]=min(F[st][i],F[st][j]+F[st][i^j]);
int head=0,tail=0;
for (int st=1; st<=n; st++) stack[++tail]=st;
for (int st=1; st<=n; st++) instack[st]=1;
while (head<tail){
int x=stack[++head];
instack[x]=0;
for (int I=last[x]; I; I=e[I].next){
int V=e[I].to;
if (F[V][i]>F[x][i]+e[I].val){
F[V][i]=F[x][i]+e[I].val;
if (!instack[V]){
instack[V]=1;
stack[++tail]=V;
}
}
}
}
}
for (int i=0; i<(1<<p); i++) cost[i]=1e9;
for (int i=0; i<(1<<p); i++)
for (int st=1; st<=n; st++)
cost[i]=min(cost[i],F[st][i]);
for (int i=1; i<=p; i++) c[i]=q[i-1].c;
sort(c+1,c+p+1);
Num=unique(c+1,c+p+1)-c-1;
for (int i=0; i<p; i++) q[i].c=lower_bound(c+1,c+Num+1,q[i].c)-c;
for (int i=0; i<p; i++) sta[q[i].c]|=(1<<i);
for (int i=0; i<(1<<Num); i++) G[i]=1e9;
dfs(1,0,0);
for (int i=0; i<(1<<Num); i++)
for (int j=i; j; j=(j-1)&i)
G[i]=min(G[i],G[j]+G[i^j]);
printf("%d\n",G[(1<<Num)-1]);
return 0;
}