时间限制:2000MS内存限制:256000KB
题目描述
给定一个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。 Data Constraint 20%的数据n<=10。 50%的数据n<=1000。 另有20%的数据k=0。 100%的数据n<=50000,m<=100000,0<=k<=10,1<=z<=5000。
spfa跑每一个必经点和起点终点,最后深搜找出必经点的顺序。
当然,如果例如点1到点3的最短路经过了一个必经点2,那么程序就会去再走向2.,相当于重复走了。
而到程序运行到从点1到点2再到点3,那么就相当于点1到点3的最短路,且不会在走向点2,所以就会比上面那样小(那样的答案是错误的),所以就会将上面错误的答案覆盖,就不需要在考虑最短路中是否有必经点了。
CODE
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<set>
#include<iostream>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 50009
#define M 100006
#define maxlong 0xffffffff
using namespace std;
int n,m;
int k,s,tt;
int next[M*10];
int list[N*10];
long long w[20][N];
int p[N*3];
bool t[N];
long x;
int y[N*10];
int z[N*10];
int ss[20];
bool e[20];
long long minn;
long long ans;
inline int look(int x)
{
for(int i=1;i<=k;i++)
if(ss[i]==x)return i;
}
inline void spfa(int k)
{
int l=0;
int r=1;
while(l<=r)
{
int f=p[++l];
int s=list[f];
while(s!=0)
{
if(z[s]+w[k][f]<w[k][y[s]])
{
w[k][y[s]]=z[s]+w[k][f];
if(!t[y[s]])
{
t[y[s]]=1;
p[++r]=y[s];
}
}
s=next[s];
}
t[p[l]]=0;
}
}
inline void start(int i,int j)//i第几号点
{
t[i]=1;
p[1]=i;
int l=look(i);
if(j==1)l=0;
if(j==2)l=k+1;
w[l][i]=0;
spfa(l);
}
inline void find(int x,int now)
{
if(x>k)
if(ans+w[now][tt]<minn)
{
minn=ans+w[now][tt];
return;
}
for(int i=1;i<=k;i++)
{
int num=ss[i];
if(!e[i])
{
e[i]=1;
ans+=w[now][num];
find(x+1,i);
e[i]=0;
ans-=w[now][num];
}
}
}
int main()
{
scanf("%d%d%d%d%d",&n,&m,&k,&s,&tt);
ss[0]=s;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y[i],&z[i]);
next[i]=list[x];
list[x]=i;
}
for(int i=0;i<20;i++)
for(int j=0;j<=n;j++)
w[i][j]=maxlong;
start(s,1);
ss[k+1]=tt;
start(tt,2);
for(int i=1;i<=k;i++)
{
scanf("%d",&ss[i]);
start(ss[i],0);
}
minn=maxlong;
find(1,0);
if(minn!=maxlong)printf("%lld",minn);
else printf("-1");
}