2019暑假集训DAY4(problem1.path)(最短路)
此题改编自[NOIP2014]day2t2寻找道路
题面
1 path
1.1 Description
众所周知,Bfk经常为找不到路而烦恼
Bfk终于迎来了它高中以来第一个完整的暑假,它决定从假期里抽出一段时间去日本旅游。可是,对于连教师宿舍都找不到的Bfk来说,在旅途中不迷路是一件很困难的事情。为了避免迷路的尴尬,Bfk早早的就规划起了它的行程。它将日本的地图抽象成了一张n个点m条边的有向图,并在上面选定了行程的起点和终点,但它在规划旅行路径时却犯了难。它希望路径上的点都满足该点的出边所指向的点都能直接或间接的到达终点,这样即使它走错了路,也能重新规划路线到达终点。另外,它还希望旅行的路程尽可能短,以便节约更多的时间预习大学课程。
现在,Bfk找到了你,希望你能帮帮它。它不想为难你,因此你不用输出具体的方案,只需要告诉它满足条件的路径的最短长度就可以了
1.2 Input
第一行两个整数 和 ,含义如题
接下来m行,每行三个整数 ,描述一条从 指向 的单向边,长度为
接下来一行两个整数 ,表示起点和终点
1.3 Output
输出一行一个数字,表示满足要求的路径的最短长度
特别的,如果不存在这样的路径,则输出“-1”(不含引号)
1.4 Sample Input
3 2 1 1 2 1 2 1 1 1 3 1 |
1.5 Sample output
-1 |
解释:起点为1号点,终点为3号点,此两点不连通,故输出-1
1.6 Note
对于 15% 的数据,
对于 30% 的数据,
对于 50% 的数据,
对于全部数据, 数据有梯度
1.7 Hint
本题附有大样例,见下发文件
其实题意就是求S到T的最短路,但题目中有一点值得注意路径上的点都满足该点的出边所指向的点都能直接或间接的到达终点
这就是一个很大的坑点了(主要是wys大佬给的数据都完美的避过了这一点,数据都是假的╭(╯^╰)╮)
那我们要如何处理这一限制呢?
就是说,如果某个点要成为最短路上的点的话,与它相连的所有点都可以通往T,我们可以预处理一下,先从T倒着dfs,能遍历到的点就可能成为最短路上的点(用一个数组YES打标记),dfs完后,对于每一个有YES标记的点,我们再判断一下与它相连的点有没有YES标记,如果没有,说明这个点也是不可以的,YES标记要去掉。
注意:若与i点(i点有YES标记)相连的j点没有YES标记,不要立即就去掉i点的YES标记,因为可能还存在着另一个k点(有YES标记)与i是相连的,如果这时就去掉了i的YES标记,可能使得k本来是可以有YES标记的却没有了。(k在i的后面进行判断YES标记的情况)
#include<bits/stdc++.h> #define N 100003 #define M 500003 #define INF 2100000001 #define LL long long using namespace std; int read() { int f=1,x=0;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } LL dis[N]; int vis[N],YES[N],NO[N],n,m; struct Edge{ int v;LL cost; Edge(int _v=0,LL _cost=0):v(_v),cost(_cost){} }; struct cun{ int x,y,z; }w[M]; vector <Edge> E[M]; struct qnode{ int v; LL c; qnode(int _v=0,LL _c=0):v(_v),c(_c){} bool operator <(const qnode &r) const { return c>r.c; } }; void add(int a,int b,int c) { E[a].push_back(Edge(b,c)); } void dfs(int x) { YES[x]=1; for(int i=0;i<E[x].size();++i) { int v=E[x][i].v; if(!YES[v])dfs(v); } } void dij(int s,int t) { for(int i=1;i<=n;++i) { vis[i]=0;dis[i]=INF; } priority_queue<qnode> q; while(!q.empty())q.pop(); dis[s]=0; q.push(qnode(s,0)); while(!q.empty()) { int u=q.top().v; q.pop(); if(vis[u]||!YES[u])continue; vis[u]=1; for(int i=0;i<E[u].size();++i) { int v=E[u][i].v; LL cost=E[u][i].cost; if(YES[v]&&!vis[v]&&dis[v]>dis[u]+cost) { dis[v]=dis[u]+cost; q.push(qnode(v,dis[v])); } } } } int main() { freopen("path.in","r",stdin); freopen("path.out","w",stdout); n=read(),m=read(); for(int i=1;i<=n;++i) E[i].clear(); for(int i=1;i<=m;++i) w[i].x=read(),w[i].y=read(),w[i].z=read(); int s=read(),t=read(); for(int i=1;i<=m;++i)add(w[i].y,w[i].x,w[i].z); dfs(t); if(!YES[s]){printf("-1\n");return 0;} for(int i=1;i<=n;++i) E[i].clear(); for(int i=1;i<=m;++i)add(w[i].x,w[i].y,w[i].z); for(int i=1;i<=n;++i) if(YES[i]) for(int j=0;j<E[i].size();++j) if(!YES[E[i][j].v]){NO[i]=1;break;} for(int i=1;i<=n;++i) if(NO[i])YES[i]=0; dij(s,t); printf("%lld\n",(dis[t]==INF)?-1:dis[t]); }
这道题的数据wys大佬卡了spfa(关于spfa它死了),所以以后还是都打dijkstra+优先队列优化吧,rua。