题目大意:
给定一个有向图,N个点M条边,有k个特殊点,请问从S出发到T的最短路径(必须经过k个特殊点 全部)
解题思路:
SPFA + dfs
初始化后跑K+1次SPFA 计算出S的单源最短路径&所有特殊点的单源最短路径,用dis[i][j]表示第j个特殊点到i的最短路径,特殊的,dis[i][0]表示S到i的最短路径
然后就爆搜求最优解
Accepted code:
注释版:
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define r(i,a,b) for (register int i=a;i<=b;i++)
using namespace std;
const long long inf=1e18;
struct node {
int x,to,l,next;
}e[100001];
bool v[50001],b[50001];
int last[50001];
long long d[50001][13],ans;
int n,m,k,s,t,cnt;
inline int read() {
int x=0; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
return x;
}
void add(int x,int y,int z) {
e[++cnt].to=y; e[cnt].l=z; e[cnt].next=last[x]; last[x]=cnt;
}
void init() {
memset(last,-1,sizeof(last));
n=read();m=read();k=read();s=read();t=read();
r(i,1,m) {
int x=read(),y=read(),z=read();
add(x,y,z);
}
r(i,1,k)
e[i].x=read();
}
void Spfa(int S,int X) {//SPFA就不说了
queue<int> que;
r(i,0,50000) d[i][X]=inf;
memset(v,0,sizeof(v));
v[S]=1; que.push(S); d[S][X]=0;
while (que.size()) {
int x=que.front(); que.pop(); v[x]=0;
for (int i=last[x];~i;i=e[i].next) {
int y=e[i].to;
if (d[y][X]>d[x][X]+e[i].l) {
d[y][X]=d[x][X]+e[i].l;
if (!v[y]) {
v[y]=1;
que.push(y);
}
}
}
}
}
void Print(long long x) {//优化输出
if (x>9) Print(x/10); putchar(x%10+48); return;
}
void dfs(int dep,long long sum,int fa) {
if (dep==k) {ans=min(sum+d[t][fa],ans); return;}
//如果已经找到了,ans求min值
for (int i=1;i<=k;i++) //遍历下去
if (!b[i]) {
b[i]=1;//标记
sum+=d[e[i].x][fa];//求出走这个点的距离之和
dfs(dep+1,sum,i);
sum-=d[e[i].x][fa];//为下个点做准备
b[i]=0;//取消标记
}
}
void Spfa_Main() {
Spfa(s,0);//首先求出dis[i][0]
for (int i=1;i<=k;i++)
Spfa(e[i].x,i);//求出每一个特殊点到所有点的最短路径
ans=inf; dfs(0,0,0); //初始化ans,进入爆搜
if (ans>=inf) printf("-1");
else
Print(ans);//如果不能满足条件则输出-1
//否则当然是输出ans啦~
}
int main() {
init();//初始化什么的
Spfa_Main();
return 0;
}
无注释版:
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define r(i,a,b) for (register int i=a;i<=b;i++)
using namespace std;
const long long inf=1e18;
struct node {
int x,to,l,next;
}e[100001];
bool v[50001],b[50001];
int last[50001];
long long d[50001][13],ans;
int n,m,k,s,t,cnt;
inline int read() {
int x=0; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
return x;
}
void add(int x,int y,int z) {
e[++cnt].to=y; e[cnt].l=z; e[cnt].next=last[x]; last[x]=cnt;
}
void init() {
memset(last,-1,sizeof(last));
n=read();m=read();k=read();s=read();t=read();
r(i,1,m) {
int x=read(),y=read(),z=read();
add(x,y,z);
}
r(i,1,k)
e[i].x=read();
}
void Spfa(int S,int X) {
queue<int> que;
r(i,0,50000) d[i][X]=inf;
memset(v,0,sizeof(v));
v[S]=1; que.push(S); d[S][X]=0;
while (que.size()) {
int x=que.front(); que.pop(); v[x]=0;
for (int i=last[x];~i;i=e[i].next) {
int y=e[i].to;
if (d[y][X]>d[x][X]+e[i].l) {
d[y][X]=d[x][X]+e[i].l;
if (!v[y]) {
v[y]=1;
que.push(y);
}
}
}
}
}
void Print(long long x) {
if (x>9) Print(x/10); putchar(x%10+48); return;
}
void dfs(int dep,long long sum,int fa) {
if (dep==k) {ans=min(sum+d[t][fa],ans); return;}
for (int i=1;i<=k;i++)
if (!b[i]) {
b[i]=1;
sum+=d[e[i].x][fa];
dfs(dep+1,sum,i);
sum-=d[e[i].x][fa];
b[i]=0;
}
}
void Spfa_Main() {
Spfa(s,0);
for (int i=1;i<=k;i++)
Spfa(e[i].x,i);
ans=inf; dfs(0,0,0);
if (ans>=inf) printf("-1");
else
Print(ans);
}
int main() {
init();
Spfa_Main();
return 0;
}