【题目描述】:
给定一个n个点m条边的有向图,有k个标记点,要求从规定的起点按任意顺序经过所有标记点到达规定的终点,问最短的距离是多少。
【输入描述】:
第一行5个整数n、m、k、s、t,表示点个数、边条数、标记点个数、起点编号、终点编号。
接下来m行每行3个整数x、y、z,表示有一条从x到y的长为z的有向边。
接下来k行每行个整数表示标记点编号。
【输出描述】:
输出一个整数,表示最短距离,若没有方案可行输出-1。
【样例输入】:
3 3 2 1 1
1 2 1
2 3 1
3 1 1
2
3
【样例输出】:
3
【样例说明】:
路径为1->2->3->1。
【时间限制、数据范围及描述】:
时间:1s 空间:256M
20%的数据n<=10。
50%的数据n<=1000。
另有20%的数据k=0。
100%的数据n<=50000,m<=100000,0<=k<=10,1<=z<=5000。
【解题思路】
模板题,最短路+dfs
【code】
1 #include<iostream>
2 #include<cstdio>
3 #include<cstdlib>
4 #include<cstring>
5 #include<cmath>
6 #include<algorithm>
7 #include<ctime>
8 #include<queue>
9 using namespace std;
10 const int N=100005,M=15;
11 long long INF=0x7fffffffffffffff;
12 using namespace std;
13 int n,m,k,S,T,flag[M],head[N],Next[N],to[N],val[N],cnt;
14 long long f[M][M],d[N],ans=INF,sum;
15 bool visit[N],vis[M];
16 priority_queue<pair<long long,int>,vector<pair<long long,int> >,greater<pair<long long,int> > >q;
17 void add(int x,int y,int z){
18 to[++cnt]=y;
19 val[cnt]=z;
20 Next[cnt]=head[x];
21 head[x]=cnt;
22 }
23 void dijkstra(int s){
24 for(int i=1;i<=n;i++){
25 d[i]=INF;
26 }
27 memset(visit,0,sizeof(visit));
28 d[s]=0;
29 q.push(make_pair(d[s],s));
30 while(!q.empty()){
31 int x=q.top().second;
32 q.pop();
33 if(visit[x]){
34 continue;
35 }
36 visit[x]=1;
37 for(int i=head[x];i;i=Next[i]){
38 int y=to[i];
39 if(d[y]>d[x]+val[i]){
40 d[y]=d[x]+val[i];
41 q.push(make_pair(d[y],y));
42 }
43 }
44 }
45 }
46 void dfs(int x,int fa){
47 if(x==k){
48 ans=min(ans,sum+f[fa][k+1]);
49 return;
50 }
51 for(int i=1;i<=k;i++){
52 if(!vis[i]){
53 vis[i]=1;
54 sum+=f[fa][i];
55 dfs(x+1,i);
56 vis[i]=0;
57 sum-=f[fa][i];
58 }
59 }
60 }
61 int main(){
62 int u,v,w;
63 scanf("%d%d%d%d%d",&n,&m,&k,&S,&T);
64 flag[0]=S;flag[k+1]=T;
65 for(int i=1;i<=m;i++){
66 scanf("%d%d%d",&u,&v,&w);
67 add(u,v,w);
68 }
69 for(int i=1;i<=k;i++){
70 scanf("%d",&flag[i]);
71 }
72 for(int i=0;i<=k+1;i++){
73 dijkstra(flag[i]);
74 for(int j=0;j<=k+1;j++){
75 f[i][j]=d[flag[j]];
76 }
77 }
78 dfs(0,0);
79 if(ans==INF){
80 printf("-1\n");
81 }
82 else{
83 printf("%lld\n",ans);
84 }
85 return 0;
86 }