地震(damage.pas/c/cpp)
【题目描述】
农夫John的农场遭受了一场地震。有一些牛棚遭到了损坏,但幸运地,所有牛棚间的路经都还能使用。 FJ的农场有P(1 <= P <= 30,000)个牛棚,编号1..P, C(1 <= C <= 100,000)条双向路经连接这些牛棚,编号为1..C。 路经i连接牛棚a_i和b_i (1 <= a_i<= P;1 <= b_i <= P),路经可能连接a_i到它自己,两个牛棚之间可能有多条路经。农庄在编号为1的牛棚.,N (1 <= N <= P)头在不同牛棚的牛通过手机短信report_j(2 <= report_j <= P)告诉FJ它们的牛棚(report_j)没有损坏,但是它们无法通过路经和没有损坏的牛棚回到到农场。 当FJ接到所有短信之后,找出最小的不可能回到农庄的牛棚数目。这个数目包括损坏的牛棚。
【输入格式】
* 第1行: 三个空格分开的数: P, C, 和 N * 第2..C+1行: 每行两个空格分开的数: a_i 和 b_i * 第C+2..C+N+1行: 每行一个数: report_j
【输出格式】
* 第1行: 一个数,最少不能回到农庄的牛的数目(包括损坏的牛棚).
【输入样例】
4 3 1
1 2
2 3
3 4
3
【输出样例】
3
【hint】
牛棚2遭到损坏,导致牛棚2, 3, 4里面的牛无法回到农庄.
贪心,首先分析,如果一个点打电话说到达不了,那么,沿 1 号点向这个点往后,所有的点都到达不了。所以,这个点连到 1 号点路径上它前面的最后一个点一定有一个是坏的(为了影响最小,贪心)。
最后遍历图,确定有哪些点不能到达。
代码(dsqwwe)
program dsqwwe;
var
sb,v:array[1..50000] of boolean;
d,first:array[1..50000] of longint;
next,t:array[1..3000000] of longint;
n,m,c,i,a,b,p,closed,open,o,x:longint;
procedure add(a,b:longint);
begin
inc(o);
t[o]:=b;
next[o]:=first[a];
first[a]:=o;
end;
begin
assign(input,'damage.in');
reset(input);
assign(output,'damage.out');
rewrite(output);
readln(n,m,c);
for i:=1 to m do
begin
readln(a,b);
add(a,b);
add(b,a);
end;
for i:=1 to c do
begin
readln(a);
p:=first[a];
while p<>0 do
begin
sb[t[p]]:=true;
p:=next[p];
end;
end;
if not sb[1] then
begin
closed:=1; open:=1;
d[1]:=1;
v[1]:=true;
while closed<=open do
begin
x:=d[closed];
p:=first[x];
while p<>0 do
begin
if (not v[t[p]]) and (not sb[t[p]]) then
begin
inc(open);
d[open]:=t[p];
v[t[p]]:=true;
end;
p:=next[p];
end;
inc(closed);
end;
writeln(n-open);
end
else writeln(n);
close(input);
close(output);
end.