UOJ #556. 神奇的道路
题目背景
在某教练的强迫之下,我一个蒟蒻居然又出题了!!!出题了!!!(数据太水别找我qwq)
好的,JL说好的一题100快拿来
题目描述
我们有一个有向图,每条边权值为1,我们要在上面找一条神奇的道路满足:
1.神奇的道路上的所有点的出边所指向的点都直接或间接与终点连通。
2.在满足条件1的情况下使路径最短。
3.该路径是从起点到终点的路径
垃圾出题人表示找不到这条路径,所以希望你帮忙qwq
输入格式
第一行有两个用一个空格隔开的整数 n 和 m,表示图有 n个点和 m 条边。
接下来的 m 行每行 2 个整数 x,y,之间用一个空格隔开,表示有一条边从点 x 指向点y。
最后一行有两个用一个空格隔开的整数 s, t,表示起点为 s,终点为 t。
输出格式
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出“orz”(不含双引号)
输入输出样例
输入#1
3 2
1 2
2 1
1 3
输出#1
orz
输入#2
7 8
5 2
3 1
5 3
1 6
3 6
6 7
2 7
2 4
5 7
输出#2
3
说明/提示
对于样例一: 起点1与终点3不连通,所以满足题目描述的路径不存在,故输出orz。
数据范围
30%保证是连通图
100% 0<n≤10000,0<m≤200000,0<x,y,s,t≤n,x,s≠t。
思路
最短路+DFS
代码:
#include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=200010; const int oo=0x3f3f3f3f; int n,m,x,y,s,t; int tot,head[N]; int cnt[N],dis[N]; int vis[N],kdl[N]; struct no { int to,nxt,dis; } map[N]; struct nod { int pos,num; }; queue<int> q; queue<int> p; void add(int u,int v,int w) { tot++; map[tot].to=v; map[tot].nxt=head[u]; map[tot].dis=w; head[u]=tot; } void spfa(int s) { memset(dis,0x3f,sizeof(dis)); dis[s]=0; q.push(s); while(q.size()) { int tmp=q.front(); q.pop(); for(int i=head[tmp]; i; i=map[i].nxt) { int v=map[i].to; if(vis[v]) continue; if(dis[v]>dis[tmp]+map[i].dis) { dis[v]=dis[tmp]+map[i].dis; q.push(v); } } } } void dfs(int s) { p.push(s); while(p.size()) { int tmp=p.front(); p.pop(); for(int i=head[tmp]; i; i=map[i].nxt) { int v=map[i].to; cnt[v]--; if(!kdl[v]) { p.push(v); kdl[v]=1; } } } } int main () { scanf("%d%d",&n,&m); for(int i=1; i<=m; i++) { scanf("%d%d",&x,&y); add(y,x,1); cnt[x]++; } scanf("%d%d",&s,&t); dfs(t); for(int i=1; i<=n; i++) if(cnt[i]) vis[i]=1; spfa(t); if(dis[s]>=oo) printf("orz\n"); else printf("%d\n",dis[s]); return 0; }