poj1144(割点)

题意:给出N,表示网络数;在每个街区的第一行中,有N<100的位置数,再给出一个最多N行的每一行都包含一个地方的数目,然后是从这个地方直接到的一些地方的数目。代表第一个数和后面的其他数都是连接的。
求割点的数目:
注意求解割点的内容:以下内容是在自己学习中总结出来的:
1.割点:在无向图中,若删去该点后图不连通,则此点为割点。
2.low[u]定义:表示在DFS回溯的前提下,该节点vi不通过父节点到vi这条边所能连通的顶点时间戳最小值。初始时,low[i]=dfn[i]当dfs处理到末尾的向前回溯,同时维护:low[fa]=min{low[fa],low[child]}
3.dfn[i]:表示在DFS回溯的前提下,该节点vi被遍历的时间先后顺序,顺序递增。
4.顶点u的割点的条件:
(1).特判树根:u为树根,且u有多于一个子树
(2).u不为树根:在递归树上u有子节点v,满足:dfn[u] <=low[v]

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxx=105;
const int inf=0x3f3f3f3f;
int dfn[maxx];
int low[maxx];
int n,m;
int root,index;
int flag[maxx];
vector<int>G[maxx];
void dfs(int u){
	index++;
	int child=0;
	dfn[u]=low[u]=index;
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		if(dfn[v]==0){
			child++;
			dfs(v);
			low[u]=min(low[u],low[v]);
			if(u!=root&&low[v]>=dfn[u]){
				flag[u]=1;
			}else
			if(u==root&&child>1){
				flag[u]=1;
			}
		}else {
			low[u]=min(low[u],dfn[v]);
		}
	}
}
int main(){
	while(scanf("%d",&n)!=EOF){
		if(n==0)break;
		memset(low,0,sizeof(low));
		memset(dfn,0,sizeof(dfn));
		memset(flag,0,sizeof(flag));
		for(int i=0;i<=n;i++){
			G[i].clear();
		}
		root=1,index=1;
		int t,tt;
		while(scanf("%d",&t)==1){
			if(t==0)break;
            while(getchar()!='\n'){
                scanf("%d",&tt);
                G[t].push_back(tt); 
                G[tt].push_back(t); 
            }
        }
		int ans=0;
		dfs(1);
		for(int i=1;i<=n;i++){
			if(flag[i]==1){
				ans++;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页