WikiOI 1332 上白泽慧音 (最裸 强连通)

1332 上白泽慧音
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题解
题目描述 Description
给出N个点和M条单向边,求最大的强连通分量并且输出最大强连通分量中的所有点

输入描述 Input Description
第1行:两个正整数N,M

第2..M+1行:每行三个正整数a,b,t, t = 1表示存在从村庄a到b的单向道路,t = 2表示村庄a,b之间存在双向通行的道路。保证每条道路只出现一次。

输出描述 Output Description
第1行: 1个整数,表示最大的绝对连通区域包含的村庄个数。

第2行:若干个整数,依次输出最大的绝对连通区域所包含的村庄编号。

样例输入 Sample Input
5 5

1 2 1

1 3 2

2 4 2

5 1 2

3 5 1

样例输出 Sample Output
3

1 3 5

数据范围及提示 Data Size & Hint
对于60%的数据:N <= 200且M <= 10,000

对于100%的数据:N <= 5,000且M <= 50,000

学强连通算法之后的第一道练习题,也算是一个基础吧,至少tarjan算法求强连通分量没有什么变动,重点是程序里的 dfs(tarjan)部分

program mys;
type 
ab=^node;
node=record
a:longint;
c:ab;
end;

var k,kk,y,i,j,m,n,x,max,z,h,t:longint;
s,ss:array[0..10000]of boolean;
low,c,f:array[0..10000]of longint;
p:array[0..10000]of ab;

function find(x:longint):longint;
begin 
if x<>f[x] then f[x]:=find(f[x]);
find:=f[x];
end;

procedure put(x,y:longint);
var i:ab;
begin 
i:=p[x];
new(p[x]);
p[x]^.a:=y;
p[x]^.c:=i;
end;

procedure dfs(x:longint);
var y:longint;
i:ab;
begin 
inc(t);
s[x]:=true;
ss[x]:=true;
low[x]:=t;
i:=p[x];
while i<>nil do 
begin 
y:=i^.a;
if s[y]=false then 
dfs(y);
y:=find(y);
if (ss[y]=true)and(low[y]then 
begin 
f[x]:=y;
low[x]:=low[y];
end;
i:=i^.c;
end;
ss[x]:=false;
end; 

begin
readln(n,m);
for i:=1 to m do 
begin 
readln(x,y,z);
put(x,y);
if z=2 then 
put(y,x);
end;
for i:=1 to n do 
begin 
s[i]:=false;
ss[i]:=false;
f[i]:=i;
end;

for i:=1 to n do 
if s[i]=false then 
begin 
fillchar(low,sizeof(low),0);
t:=0;
dfs(i);
end;
max:=0;
for i:=1 to n do 
inc(c[find(i)]);
for i:=1 to n do 
if c[find(i)]>max then 
max:=c[find(i)];

writeln(max);
for i:=1 to n do 
if c[find(i)]=max then 
begin 
k:=find(i);
kk:=i;
break;
end;

for i:=kk to n do 
if find(i)=k then 
write(i,' ');
end.

你可能感兴趣的:(强连通)