在线评测:
http://codevs.cn/problem/3731/
整体思路:
先从(在反向图中)终点dfs一遍,然后所有能到达在dfs中没有搜到的点也标记为不可用,然后正向bfs跑最短路就行,
失误之处:
最开始从起点开始bfs判断哪些点不可用,但是后来发现这样子很多事情在递归里很难处理,于是又想到从每个点都dfs一遍,但是这样子的n2算法太慢了!!!!!所以最后想到从终点开始搜索,
开始我将dfs没有搜到的点全部dfs一遍(反向图),将dfs的点全部标记为不可用,,,然后GG
体会心得:
在面对有起点有终点的情况下,想一下起点和终点有什么区别,换着用有没有什么好处或优势,
写代码前一定仔细想好自己算法的可行性!
AC代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
using
namespace
std;
int
n,m,x,y,s,t,sum,cnt;
int
head[20010],nxt[500000],to[500000],dis[20010];
int
nhead[20010],nnxt[500000],nto[500000],ans;
bool
dvis[20010],fky[20010],vis[20010];
queue <
int
> dl,js;
void
cr(
int
x,
int
y)
{
sum++;
nxt[sum] = head[x];
head[x] = sum;
to[sum] = y;
}
void
ncr(
int
x,
int
y)
{
cnt++;
nnxt[cnt] = nhead[x];
nhead[x] = cnt;
nto[cnt] = y;
}
void
dfs(
int
x)
{
for
(
int
tp = nhead[x];tp;tp = nnxt[tp])
{
if
(!dvis[nto[tp]])
{
dvis[nto[tp]] =
true
;
dfs(nto[tp]);
}
}
}
void
ndfs(
int
x)
{
for
(
int
tp = nhead[x];tp;tp = nnxt[tp])
{
if
(!fky[nto[tp]])
{
fky[nto[tp]] =
true
;
// ndfs(nto[tp]);
}
}
}
void
bfs(
int
x)
{
dl.push(x);
js.push(0);
vis[x] =
true
;
while
(!dl.empty())
{
if
(dl.front() == t)
{
ans = js.front();
return
;
}
for
(
int
tp = head[dl.front()];tp;tp = nxt[tp])
{
if
(!fky[to[tp]] && !vis[to[tp]])
{
dl.push(to[tp]);
js.push(js.front()+1);
vis[to[tp]] =
true
;
}
}
dl.pop();
js.pop();
}
}
int
main()
{
scanf
(
"%d%d"
,&n,&m);
for
(
int
i = 1;i <= m;i++)
{
scanf
(
"%d%d"
,&x,&y);
cr(x,y);
ncr(y,x);
}
scanf
(
"%d%d"
,&s,&t);
dvis[t] =
true
;
dfs(t);
for
(
int
i = 1;i <= n;i++)
{
if
(!dvis[i]) ndfs(i);
}
bfs(s);
if
(ans || s == t)
printf
(
"%d\n"
,ans);
else
printf
(
"-1\n"
);
return
0;
}
|