洛谷P2296寻找道路

传送门啦

题目中有一个条件是路径上的所有点的出边所指向的点都直接或间接与终点连通。

所以我们要先判断能否走这一个点, $ bfs $ 类似 $ spfa $ 的一个判断,打上标记。

在这我反向建图,最后跑最短路的时候就从终点跑到起点,也是一样的。在最短路中加上一个判断就好了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define re register
using namespace std;
const int maxn = 10005;
const int maxm = 200005;

inline int read(){
	char ch = getchar();
	int f = 1 , x = 0;
	while(ch > '9' || ch < '0' ) { if(ch == '-')f = -1;ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3 ) + ch - '0';ch = getchar();}
	return x * f;
}

int n , m , x , y , s , t ;
int head[maxn] , tot ;
bool vis[maxm] , ok[maxm] ;

struct Edge{
	int from,to,next,val;
}edge[maxm << 1];

struct Node {
	int u , d;
	bool operator < (const Node &f) const {
		return d > f.d;
	}
};

inline void add(int u , int v , int w){
	edge[++tot].from = u ;
	edge[tot].to = v ;
	edge[tot].val = w;
	edge[tot].next = head[u];
	head[u] = tot ;
}

inline void bfs(int t){
	queue<int>  que;
	memset(vis , false , sizeof(vis) );
	que.push(t);
	vis[t] = true;
	ok[t] = true;
	while( !que.empty() ){
		int cur = que.front();
		que.pop();
		for(re int i = head[cur] ; i ; i = edge[i].next){
			int v = edge[i].to ;
			if(vis[v] == false){
				ok[v] = true ;
				vis[v] = true;
				que.push(v);
			}
		}
	}
}

int dis[maxn];
inline void dijk(int t){
	for(re int i = 1 ;i <= n ; ++i) dis[i] = 1e9;
	priority_queue<Node> q;
	dis[t] = 0;
	q.push( (Node) {t , dis[t]});
	while( ! q.empty() ){
		Node cur = q.top();
		q.pop() ;
		int d = cur.d , u = cur.u ;
		if(d != dis[u]) continue;
		for(re int i = head[u] ; i; i = edge[i].next){
			int v = edge[i].to;
			if(ok[v])  continue;
			if(dis[v] > dis[u] + edge[i].val){
				dis[v] = dis[u] + edge[i].val;
				q.push( (Node) {v , dis[v]} );
			}
		}
	}
}

int main(){
	n = read(); m = read();
	for(re int i = 1 ; i <= m ; ++i) {
		x = read();  y = read(); 
		add(y , x , 1);
	}
	s = read() ; t = read() ;
	bfs(t) ;
	for(re int i = 1 ; i <= n ; ++i){
		vis[i] = ok[i];
	}
	memset(ok , false , sizeof(ok));
	for(int i = 1 ; i <= n ; ++i){
		if(!vis[i]) {
			for(re int j = head[i] ; j ; j = edge[j].next) {
				int v = edge[j].to;
				ok[v] = true; 
			}
		}
	}
	dijk(t) ;
	if(dis[s] != 1e9)  printf("%d
",dis[s]);
	else printf("-1
");
	return 0;
}
原文地址:https://www.cnblogs.com/Stephen-F/p/9925574.html