1. 程式人生 > >POJ 1144——Network 求割點

POJ 1144——Network 求割點

https://vjudge.net/problem/20837/origin

求割點問題

該演算法是R.Tarjan發明的。對圖深度優先搜尋,定義DFS(u)為u在搜尋樹(以下簡稱為樹)中被遍歷到的次序號。定義Low(u)為u或u的子樹中能通過非父子邊追溯到的最早的節點,即DFS序號最小的節點。根據定義,則有:

Low(u)=Min { DFS(u) DFS(v) (u,v)為後向邊(返祖邊) 等價於 DFS(v)<DFS(u)且v不為u的父親節點 Low(v) (u,v)為樹枝邊(父子邊) }

一個頂點u是割點,當且僅當滿足(1)或(2) (1) u為樹根,且u有多於一個子樹。 (2) u不為樹根,且滿足存在(u,v)為樹枝邊(或稱父子邊,即u為v在搜尋樹中的父親),使得DFS(u)<=Low(v)。

A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places numbered by integers from 1 to N. No two places have the same number. The lines are bidirectional and always connect together two places and in each place the lines end in a telephone exchange. There is one telephone exchange in each place. From each place it is possible to reach through lines every other place, however it need not be a direct connection, it can go through several exchanges. From time to time the power supply fails at a place and then the exchange does not operate. The officials from TLC realized that in such a case it can happen that besides the fact that the place with the failure is unreachable, this can also cause that some other places cannot connect to each other. In such a case we will say the place (where the failure occured) is critical. Now the officials are trying to write a program for finding the number of all such critical places. Help them. Input The input file consists of 

#include<bits/stdc++.h>
using namespace std;
const int maxn=150;
int n;
struct node
{
	int to;
	int next;
}edge[maxn*maxn];
int head[maxn];
int index;
int tot;
int low[maxn];
int DFN[maxn];
bool instack[maxn];
bool cut_point[maxn];

void init()
{
	tot=0;
	index=0;
	memset(head,-1,sizeof(head));
	memset(cut_point,0,sizeof(cut_point));
	memset(instack,0,sizeof(instack));
}

void addedge(int from,int to)
{
	edge[tot].to=to;
	edge[tot].next=head[from];
	head[from]=tot++;
}

void tarjan(int u,int root,int fa)
{
	DFN[u]=low[u]=++index;
	instack[u]=1;
	int cnt=0;
	for(int i=head[u];i!=-1;i=edge[i].next)
	{
		int v=edge[i].to;
		if(!instack[v])
		{
			tarjan(v,root,u);
			cnt++;
			if(low[u]>low[v])
		 		low[u]=low[v];
 			if(u==root && cnt>1)
 				cut_point[u]=1;
			else if(u!=root && low[v]>=DFN[u])
				cut_point[u]=1;
		}
		else if(v!=fa && low[u] > DFN[v])
			low[u]=DFN[v];
	}
}

int search_cut_point()
{
	int ans=0;
	tarjan(1,1,-1);
	for(int i=1;i<=n;i++)
		if(cut_point[i])
			ans++;
	return ans;
}

int main()
{
	while(~scanf("%d",&n) && n)
	{
		init();
		int s,t;
		while(scanf("%d",&s) && s)
		{
			while(getchar()!='\n')
			{
				scanf("%d",&t);
				addedge(s,t);
				addedge(t,s);//加邊;
			}
		}
		printf("%d\n",search_cut_point());//進行計算;
	}
	return 0;
}