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;
}

猜你喜欢

转载自www.cnblogs.com/mysh/p/11355051.html
今日推荐