UOJ 67 新年的毒瘤 (tarjan算法求割点)

67 新年的毒瘤

辞旧迎新之际,喜羊羊正在打理羊村的绿化带,然后他发现了一棵长着毒瘤的树。

这个长着毒瘤的树可以用 nn 个结点 mm 条无向边的无向图表示。这个图中有一些结点被称作是毒瘤结点,即删掉这个结点和与之相邻的边之后,这个图会变为一棵树。树也即无简单环的无向连通图。

现在给你这个无向图,喜羊羊请你帮他求出所有毒瘤结点。

输入格式
第一行两个正整数 n,m,表示有 n 个点 m 条边。保证 n≥2。
接下来 mm 行,每行两个整数 v,u,表示 v 和 u 之间有一条无向边。1≤v,u≤n。保证没有重边和自环。

输出格式
第一行一个正整数 s,表示这个图中有 s 个结点是毒瘤。
接下来一行,共 s 个整数,每个整数表示一个毒瘤结点的编号。请按编号从小到大的顺序输出。
数据保证图中至少存在一个毒瘤结点。

样例一
input
6 6
1 2
1 3
2 4
2 5
4 6
5 6

output
3
4 5 6

题解

正解需要你理解什么叫做树。如果你对树的理解仅仅是“长得像树的家伙”就完蛋了。

我们需要用一个定义来规定什么叫做树。我们可以理解成,有 n−1n−1 条边的无向连通图。“有 n−1 条边” 提示我们最终图里有 n−2 条边,所以你需要删一个度数为 m−(n−2) 的结点。

考虑第二个条件,也就是说删掉这个点后剩下的图仍然连通,所以这个点不是割点就行了。

所以用 Tarjan 算法求割点,然后输出所有不是割点且度数满足条件的结点就行了。可以获得 100 分。

program mys;
type ab=^node;
node=record
ends:longint;
next:ab;
end;

var i,j,k,m,n,x,y,t:longint;
p:array[0..100010]of ab;
f,d,low,dfn,g,c:array[0..100010]of longint;
b:array[0..100010]of boolean;

procedure com(x,y:longint);
var i:ab;
begin 
i:=p[x];
new(p[x]);
p[x]^.ends:=y;
p[x]^.next:=i;
end;

procedure dfs(x:longint);
var i:ab;
y:longint;
begin 
inc(t);
dfn[x]:=t;
low[x]:=t;
i:=p[x];
while i<>nil do 
begin 
y:=i^.ends;
if dfn[y]=0 then 
begin 
dfs(y);
if low[y]then low[x]:=low[y];
if low[y]>=dfn[x] then inc(g[x]);
end
else if dfn[y]then low[x]:=dfn[y];
i:=i^.next;
end;
end;

begin 
readln(n,m);
for i:=1 to m do 
begin 
readln(x,y);
inc(d[x]); 
inc(d[y]);
com(x,y);
com(y,x);
end;

g[1]:=-1;
dfs(1);
t:=0;
for i:=1 to n do 
if (g[i]<=0)and(m-d[i]=n-2) then 
begin 
inc(t);
c[t]:=i;
end;
writeln(t);
for i:=1 to t do
write(c[i],' ');
end.

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