我看很多大佬都用的是bfs,我今天来发一篇dfs的题解。
但是很显然这道题dfs更好理解(自卖自夸)
很显然这道题中不是所有的边都能跑的,所以找到那些边可以走才是这道题的关键,剩下的就是一个最短路的板了,那么怎么找呢?
首先我们在建正图的时候统计每个点的出度,然后在建反图。 我们用一个cnt[]数组来存在跑反图的时候每个点能到达的次数,而且还要用一个vis[]数组来标记每个点只能跑一次。
很显然我们在跑完dfs后一个for循环遍历每个点看他的cnt[]值是不是大于等于他的出度,如果是这个点就可以跑,反之就不行。
剩下的就是一个dij的板了
话不多说直接上代码
原题链接:P2296 [NOIP2014 提高组] 寻找道路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
priority_queue<pair<int ,int> > p;
struct node {
int f,t,nex;
}rt[200010],rt1[200010];
int head[200010];
int cnt;
int head1[200010];
int cnt1;
int vis[200010];
int qaq[200010];
int chudu[200010];
int vis1[200010];
int val[200010];
void add(int x,int y) {
cnt ++;
rt[cnt].f = x;
rt[cnt].t = y;
rt[cnt].nex = head[x];
head[x] = cnt;
}
void add1(int x,int y) {
cnt1 ++;
rt1[cnt1].f = x;
rt1[cnt1].t = y;
rt1[cnt1].nex = head1[x];
head1[x] = cnt1;
}
void dfs(int x) {
if(!vis[x]) {
vis[x] = 1;
qaq[x] ++;
for (int i = head1[x]; i ; i = rt1[i].nex) {
dfs(rt1[i].t);
}
}
else {
qaq[x] ++;
}
}
int main() {
int a,b;
cin>>a>>b;
for (int i = 1; i <= b; ++i) {
int x,y;
cin>>x>>y;
chudu[x] ++;
add(x,y);
add1(y,x);
}
int f,t;
cin>>f>>t;
dfs(t);
memset(val,0x7f, sizeof(val));
val[f] = 0;
p.push(make_pair(0,f));
for (int j = 1; j <= a; ++j) {
if(chudu[j] <= qaq[j]) {
vis1[j] = 1;
}
}
while (!p.empty()) {
int faq = p.top().second;
p.pop();
for (int i = head[faq]; i ; i = rt[i].nex) {
if(vis1[rt[i].t]) {
if(val[rt[i].t] > val[faq] + 1) {
val[rt[i].t] = val[faq] + 1;
p.push(make_pair(-val[rt[i].t],rt[i].t));
}
}
}
}
if(val[t] == 0x7f7f7f7f) {
cout<<-1;
}
else {
cout<<val[t];
}
return 0;
}