Evanyou Blog 彩带

洛谷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\n",dis[s]);
	else printf("-1\n");
	return 0;
}
posted @ 2018-11-07 20:47  Stephen_F  阅读(98)  评论(0编辑  收藏  举报