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.