Description - 问题描述
本题和大多数名叫network的题目一样,是图论题。
对于一张无向连通图中一点V,如果把V删除会导致图不连通,则称V为关键点。
给出一张无向图,要求图中所有关键点,并求出删除该关键点后图被分成多少个连通块。
Input - 输入数据
第一行:两个整数:N,M,分别表示图中结点个数和边数。
接下来M行:每行两个整数X,Y(1<=X,Y<=N),中间用一个空格隔开,表示结点X和Y之间有一条通路。
数据保证:图一定连通,任意两点之间最多只有一条通路。
Output - 输出数据
第一行:S,表示关键点的个数。
如果S大于0,则接下来S行,每行两个整数V、K,中间用一个空格隔开,表示删去关键点V后图被分成K个连通块,按V从小到大输出。
Hint - 额外信息
样例输入2
5 5
1 2
2 3
3 4
4 5
5 1
样例输出2
0
样例输入3
6 7
1 2
2 3
3 4
4 6
6 3
2 5
5 1
样例输出3
2
2 2
3 2
提示
对于40%的数据,1<=N<=20
对于70%的数据,1<=N<=100
对于100%的数据,1<=N<=1000
对于100%的数据,N-1<=M<=N*(N-1)/2
----------------------------------------
看起来没有办法把这个格式搞好了233。。
不过这样也挺好的。。
嗯就是传统的求割项,再加上如果去掉这个会有多少联通块
要算去掉这个会有多少联通块,那就是在dfs的时候,有多少个儿子的low>=它的dfn,就好了
Code:
const shuru='test.in';
shuchu='test.out';
maxn=1001;
maxm=500001;
var ans,dfn,low,headlist:array[0..maxn] of longint;
next,t:array[0..maxm] of longint;
vis:array[0..maxn] of boolean;
tot,x,y,i,j,k,n,m,time,num:longint;
procedure init;
begin
readln(n,m);
for i:=1 to n do headlist[i]:=-1;
fillchar(vis,sizeof(vis),false);
for i:=1 to m do
begin
readln(x,y);
inc(num);
next[num]:=headlist[x];
headlist[x]:=num;
t[num]:=y;
inc(num);
next[num]:=headlist[y];
headlist[y]:=num;
t[num]:=x;
end;
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(b);
end;
procedure dfs(u,fa:longint);
var i:longint;
begin
inc(time); dfn[u]:=time; low[u]:=time;
vis[u]:=true;
i:=headlist[u];
while i<>-1 do
begin
if not(vis[t[i]]) then begin
dfs(t[i],u);
if u=1 then inc(ans[u])
else if low[t[i]]>=dfn[u] then inc(ans[u]);
low[u]:=min(low[u],low[t[i]]);
end
else if t[i]<>fa then low[u]:=min(low[u],dfn[t[i]]);
i:=next[i];
end;
end;
procedure main;
begin
init;
ans[1]:=-1;
dfs(1,0);
for i:=1 to n do if ans[i]>0 then inc(tot);
writeln(tot);
for i:=1 to n do if ans[i]>0 then writeln(i,' ',ans[i]+1);
end;
begin
main;
end.