1. 题目
跑步(Running.pas/c/cpp)
题目描述
新兵到部队,警官要求他们每天早上搞晨跑,从A营跑到B营。从A营到B营中有n-2个路口,分别标上号,A营为1号,B营为n号,路口分别为2..n-1号,从A营到B营有很多条路径可以到达,而睿智的警官发现有的路口是必须经过的,即每条路径都经过的路口,警官要把它们记录下来,这样警官就可以先到那个路口,观察新兵有没有偷懒,而你的任务就是找出所有必经路口。
输入数据
第一行两个用空格隔开的整数n(3<=n<=2000)和e(1<=n<=8000)。
接下来从第2到第e+1行,每行两个用空格隔开的整数p和q,表示路口p和q之间有路径直达。
输入数据保证必经路口一定存在,并且每个路口都和A营、B营相连通。
输出数据
第一行一个整数m,表示必经路口的数目。
第二行按从小到大的顺序依次输出每个必经路口的编号,每两个数之间用一个空格隔开。
注意:不包括起点和终点。
样例输入
6 6
1 2
2 4
2 3
3 5
4 5
5 6
样例输出
2
2 5
2. 题目实质
给出一个无向图,要求求出其中的关键点(从起点到终点必经过的点)。
3. 算法
注意,不要傻傻的去求割点。这个算法不好写,更重要的是,它根本不对。
这可是第一题,用不着类似于割点、桥这样的知识点。
其实,他的正解是枚举+图的遍历。
首先,枚举每一个点,再把这一个点去掉,遍历整个图,如果能走到 n ,则说明这个点不是关键点,反之,则记录。
然后,就是这样。
4. 注意事项
审题,不要求割点!
5. 程序代码
SueMiller (Pascal)
var n,e:integer;
a:array[0..2010,0..2010]of integer;
ans:array[0..2010]of integer;
v:array[0..2010]of boolean;
x,y,i,j,k:integer;
procedure dfs(x:integer);
var i:integer;
begin
v[x]:=true;
for i:=1 to a[x,0] do
if not v[a[x,i]] then dfs(a[x,i]);
exit;
end;
begin
assign(input,'Running.in');reset(input);
assign(output,'Running.out');rewrite(output);
readln(n,e);
fillchar(a,sizeof(a),false);
for i:=1 to e do
begin
read(x,y);
inc(a[x,0]);
a[x,a[x,0]]:=y;
inc(a[y,0]);
a[y,a[y,0]]:=x;
end;
fillchar(ans,sizeof(ans),0);
for k:=2 to n-1 do
begin
fillchar(v,sizeof(v),false);
v[k]:=true;
dfs(1);
if not v[n] then begin
inc(ans[0]);
ans[ans[0]]:=k;end;
end;
writeln(ans[0]);
for i:=1 to ans[0] do write(ans[i],' ');
close(input);close(output);
end.
6. 囧囧的惊残孤梦
话说,在三个月以前,本人还不会遍历一张图……甚至连邻接表都打着很费劲……不用指针根本写不出来……经典算法是按文科的学习方法------背!
时过境迁、沧海桑田啊,这个代码, 5 分钟……