K点最短路

【题目描述】:

给定一个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 }

猜你喜欢

转载自www.cnblogs.com/66dzb/p/11349046.html