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;
}

猜你喜欢

转载自blog.csdn.net/lanshan1111/article/details/84997968