最短路预处理,然后普通的状压状态转移就好了:
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define repd(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;
const int Inf=1e9;
const int N=2e4+5;
const int M=2e5+5;
int f[22][1<<20];
int n,m,t,h,ans=Inf,lim[N],vis[N],dis[22][N];
int cnt,to[M<<1],edge[M<<1],nxt[M<<1],head[M];
inline int read() {
int x=0;char ch=getchar();bool f=0;
while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?-x:x;
}
void ins(int x,int y,int z) {
to[++cnt]=y;edge[cnt]=z;nxt[cnt]=head[x];head[x]=cnt;
}
void spfa(int s) {
rep(i,1,n) vis[i]=0,dis[s][i]=Inf;
queue<int>q;q.push(s);vis[s]=1;dis[s][s]=0;
while(q.size()) {
int x=q.front();q.pop();vis[x]=0;
for(int i=head[x];i;i=nxt[i]) {
int y=to[i],z=edge[i];
if(dis[s][x]+z<dis[s][y]) {
dis[s][y]=dis[s][x]+z;
if(!vis[y]) {
vis[y]=1;q.push(y);
}
}
}
}
}
int dp(int cur,int s) {
if(~f[cur][s]) return f[cur][s];
if(s==h) return dis[cur][n];
f[cur][s]=Inf;
rep(i,2,t+1) if((s&lim[i])==lim[i]) f[cur][s]=min(f[cur][s],dis[cur][i]+dp(i,s|(1<<(i-2))));
return f[cur][s];
}
int main() {
memset(f,-1,sizeof(f));
n=read(),m=read(),t=read();h=(1<<t)-1;
rep(i,1,m) {
int x=read(),y=read(),z=read();ins(x,y,z);ins(y,x,z);
}
rep(i,1,t+1) spfa(i);
int limit=read();
rep(i,1,limit) {
int x=read(),y=read();lim[y]|=(1<<(x-2));
}
printf("%d",dp(1,0));
return 0;
}