[题目来源]:Tyvj P1111
[关键字]:有向图的连通分量
[题目大意]:给出一个图,求它的强连通分量数量
//============================================================================================================
[分析]:据说此题数据没有按有向图的强连通分量给,并查集就能过,但我还是用trajan做的(水题,练习一下)。tarjan算法和求无向图的割点、桥样子差不多,其本质也是一样的,利用dfs树和时间戳来判断,只不过比那两个算法多了一个栈,求图的连通性的还有floodfill算法求无向图的连通分量。
[代码]:
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 type
2 rec = record
3 y, n: longint;
4 end;
5 var
6 n, tot, ans, top, m: longint;
7 instack: array[0..300] of boolean;
8 stack: array[0..300] of longint;
9 dfn, lowlink, f: array[0..300] of longint;
10 e: array[0..5000] of rec;
11 link: array[0..300] of longint;
12
13 procedure make(x, y: longint);
14 begin
15 inc(m);
16 e[m].y := y;
17 e[m].n := link[x];
18 link[x] := m;
19 end;
20
21 procedure init;
22 var
23 i, y: longint;
24 begin
25 readln(n);
26 for i := 1 to n do
27 begin
28 read(y);
29 while y <> 0 do
30 begin
31 make(i,y);
32 read(y);
33 end;
34 end;
35 end;
36
37 function min(x, y: longint):longint;
38 begin
39 if x < y then exit(x) else exit(y);
40 end;
41
42 procedure tarjan(k: longint);
43 var
44 y, t: longint;
45 begin
46 inc(tot);
47 dfn[k] := tot;
48 lowlink[k] := tot;
49 instack[k] := true;
50 inc(top);
51 stack[top] := k;
52 t := link[k];
53 while t <> 0 do
54 begin
55 y := e[t].y;
56 if dfn[y] = 0 then
57 begin
58 tarjan(y);
59 lowlink[k] := min(lowlink[k],lowlink[y]);
60 end
61 else
62 if instack[y] then lowlink[k] := min(lowlink[k],dfn[y]);
63 t := e[t].n;
64 end;
65 if dfn[k] = lowlink[k] then
66 begin
67 inc(ans);
68 repeat
69 y := stack[top];
70 dec(top);
71 instack[y] := false;
72 f[y] := ans;
73 until k = y;
74 end;
75 end;
76
77 procedure work;
78 var
79 i: longint;
80 begin
81 tot := 0;
82 top := 0;
83 ans := 0;
84 fillchar(dfn,sizeof(dfn),0);
85 for i := 1 to n do
86 if dfn[i] = 0 then
87 tarjan(i);
88 writeln(ans);
89 end;
90
91 begin
92 init;
93 work;
94 end.