[NOIP2014]寻找道路
题目描述 Description
在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
1.路径上的所有点的出边所指向的点都直接或间接与终点连通。
2.在满足条件1的情况下使路径最短。
注意:图G中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入描述 Input Description
第一行有两个用一个空格隔开的整数n和m,表示图有n个点和m条边。
接下来的m行每行2个整数x、y,之间用一个空格隔开,表示有一条边从点x指向点y。
最后一行有两个用一个空格隔开的整数s、t,表示起点为s,终点为t。
输出描述 Output Description
输出文件名为road.out。
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出-1。
样例输入 Sample Input
road.in |
road.out |
3 2 1 2 2 1 1 3 |
-1 |
样例输出 Sample Output
road.in |
road.out |
6 6 1 2 1 3 2 6 2 5 4 5 3 4 1 5 |
3 |
数据范围及提示 Data Size & Hint
对于30%的数据,0< n ≤10,0< m ≤20;
对于60%的数据,0< n ≤100,0< m ≤2000;
对于100%的数据,0< n ≤10,000,0< m ≤200,000,0< x,y,s,t≤n,x≠t。
试题分析:反向建边比较好求每个点是否可以经过,DFS跑一遍就可以知道。
然后再忽略不合法的点,跑一遍SPFA 20分钟1A
代码
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<stack> #include<vector> #include<algorithm> //#include<cmath> using namespace std; const int INF = 9999999; #define LL long long inline int read(){ int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘; return x*f; } int N,M; int Node[200001],Root[200001],Next[200001]; int cnt; bool vis[10001]; int to[10001]; int dis[10001]; bool inq[10001];int que[10001]; int S,T; void addedge(int u,int v){ cnt++; Node[cnt]=v; Next[cnt]=Root[u]; Root[u]=cnt; return ; } void outto(int x){ vis[x]=true; for(int k=Root[x];k;k=Next[k]){ to[Node[k]]--; if(!vis[Node[k]]) outto(Node[k]); } return ; } int SPFA(int s,int t){ if(!vis[s]||!vis[t]) return -1; memset(inq,false,sizeof(inq)); memset(dis,INF,sizeof(dis)); dis[s]=0; inq[s]=true; int tail=1; que[tail]=s; for(int head=1;head<=tail;head++){ for(int x=Root[que[head]];x;x=Next[x]){ if(vis[Node[x]]&&dis[Node[x]]>dis[que[head]]+1){ dis[Node[x]]=dis[que[head]]+1; if(!inq[Node[x]]){ inq[Node[x]]=true; que[++tail]=Node[x]; } } } inq[que[head]]=false; } if(dis[t]>=INF) return -1; return dis[t]; } int main(){ //freopen(".in","r",stdin); //freopen(".out","w",stdout); N=read(),M=read(); for(int i=1;i<=M;i++){ int x=read(),y=read(); addedge(y,x);to[x]++; } S=read(),T=read(); outto(T); for(int i=1;i<=N;i++) if(!to[i]&&vis[i]==true) vis[i]=true; else vis[i]=false; printf("%d\n",SPFA(T,S)); return 0; }
时间: 2024-12-13 01:48:22