DFN-LOW算法---割点、桥、强连通分量

无向图:割顶:

Program gedian;
	
var
	n,m,time,x,y,sum,t,i		:longint;
	link,next,endv,dfn,low		:array[1..10000] of longint;
	b							:array[1..10000] of boolean;
	
	Procedure insert(u,v:longint);
	begin
		inc(t);
		endv[t]:=v; next[t]:=link[u]; link[u]:=t;
	end;

	Procedure DFS(x,fa:longint);
	var
		p,v:longint;
	begin
		inc(time);
		low[x]:=time; dfn[x]:=time;
		p:=link[x];
		while p<>-1 do
			if endv[p]<>fa then
				begin
					v:=endv[p];
					if dfn[v]=0 then	
						begin
							if x=1 then inc(sum);
							DFS(v,x);
							if low[v]<low[x] then low[x]:=low[v];
							if low[v]>=dfn[x] then b[x]:=true;
						end else
					if low[x]>dfn[v] then low[x]:=dfn[v];
					p:=next[p];
				end else
			p:=next[p];
	end;
	
begin
	readln(n,m);
	for i:=1 to n do link[i]:=-1;
	for i:=1 to m do 
		begin
			readln(x,y);
			insert(x,y);
			insert(y,x);
		end;
	DFS(1,1);
	if sum>=2 then writeln(1);
	for i:=2 to n do 
		if b[i] then writeln(i);
end.

 

桥:

Program bridge;

var
	next,link,endv,sta	:array[1..100000] of longint;
	dfn,low				:array[1..100000] of longint;
	b					:array[1..100000] of boolean;
	n,m,i,x,y,t,time	:longint;
	
	Procedure insert(u,v:longint);
	begin
		inc(t); 
		sta[t]:=u; endv[t]:=v; next[t]:=link[u]; link[u]:=t;
	end;
	
	Procedure DFS(x,fa:longint);
	var
		p,v:longint;
	begin
		inc(time); dfn[x]:=time; low[x]:=time;
		p:=link[x];
		while p<>-1 do
			if endv[p]<>fa then
				begin
					v:=endv[p];
					if dfn[v]=0 then
						begin
							DFS(v,x);
							if low[v]<low[x] then low[x]:=low[v];
							if low[v]=dfn[v] then b[p]:=true;
						end else
						if dfn[v]<low[x] then low[x]:=dfn[v];
					p:=next[p];
				end else
			p:=next[p];
	end;
	
begin
	readln(n,m);
	for i:=1 to n do link[i]:=-1;
	for i:=1 to m do
		begin
			readln(x,y);
			insert(x,y);
			insert(y,x);
		end;
	DFS(1,1);
	for i:=1 to t do if b[i] then writeln(sta[i],' ',endv[i]);
end.
	

 

有向图:

强联通分量

Program tarjan;

var
	link,next,endv				:array[1..10000] of longint;
	dfn,low,stack,lab,view		:array[1..10000] of longint;
	n,m,top,i,x,y,time,total	:longint;
	
	Procedure insert(t,u,v:longint);
	begin
		endv[t]:=v; next[t]:=link[u]; link[u]:=t;
	end;
	
	Procedure DFS(x:longint);
	var		
		p,v:longint;
	begin
		inc(time); dfn[x]:=time; low[x]:=time; inc(top); stack[top]:=x; view[x]:=1;
		p:=link[x];
		while p<>-1 do
			begin
				v:=endv[p];
				if view[v]=0 then DFS(v);
				if (view[v]<2) and (low[v]<low[x]) then low[x]:=low[v];
				p:=next[p];
			end;
		if dfn[x]=low[x] then	
			begin
				inc(total);
				while stack[top]<>x do
					begin
						v:=stack[top];
						view[v]:=2;
						lab[v]:=total;
						dec(top);
					end;
				lab[x]:=total; view[x]:=2; dec(top); 
			end;
	end;
	
begin
	readln(n,m);
	for i:=1 to n do link[i]:=-1;
	for i:=1 to m do 
		begin
			readln(x,y);
			insert(i,x,y);
		end;
	for i:=1 to n do if dfn[i]=0 then DFS(i);
	for i:=1 to n do writeln(lab[i]);
end.

转载于:https://www.cnblogs.com/Lr-bob/archive/2012/03/15/2399464.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值