天天看點

POJ1523:割點

POJ1523

題意:問一個連通的網絡中有多少個關節點,這些關節點分别能把網絡分成幾部分

題解:求割點的題目。給的網絡一定是連通的,割點就是在無向連通圖的前提下。最後注意輸出,每兩個Case之間有個blank。

代碼:

#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
using namespace std;
int const N = 1000 + 10;
vector<int>G[N];
int cnt,scc,T,root;
int pre[N],lowlink[N],sccno[N],son[N];
int n;
stack<int>st;
bool Init(){
	int u,v;
	n = 0;
	for(int i=0;i<N;i++)	G[i].clear();
	while(~scanf("%d",&u) && u){
		scanf("%d",&v);
		n = max(n,max(u,v));
		G[u].push_back(v);
		G[v].push_back(u);
		while(~scanf("%d",&u) && u){
			scanf("%d",&v);
			G[u].push_back(v);
			G[v].push_back(u);
			n = max(n,max(u,v));
		}
		return true;
	}
	return false;
}
void dfs(int u){
	pre[u] = lowlink[u] = ++cnt;
	st.push(u);
	for(int i=0;i<G[u].size();i++){
		int v = G[u][i];
		if(!pre[v]){
			dfs(v);
			lowlink[u] = min(lowlink[v],lowlink[u]);
			if(lowlink[v] >= pre[u]){
				if(u != root)	son[u]++;
				else	son[root]++; 
			}
		}else if(!sccno[v]){
			lowlink[u] = min(lowlink[u],pre[v]);
		}
	}
	if(pre[u] == lowlink[u]){
		scc++;
		while(1){
			int x = st.top();	st.pop();
			sccno[x]= scc;
			if(x == u)	break;
		}
	}
}
void Tarjain(){
	cnt = scc = 0;
	while(!st.empty())	st.pop();
	root = 1;
	memset(pre,0,sizeof(pre));
	memset(sccno,0,sizeof(sccno));
	memset(son,0,sizeof(son));
	dfs(1);
}
void solve(){
	if(T)	cout<<endl;
	printf("Network #%d\n",++T);
	int ans = 0;
	if(son[root] > 1)	ans++;
	for(int i=2;i<=n;i++)
		if(son[i])	ans++;
	if(!ans)	printf("  No SPF nodes\n");
	else{
		for(int i=1;i<=n;i++){
			if(i == root && son[root] > 1)
				printf("  SPF node %d leaves %d subnets\n",i,son[i]);  
			else if(i != root && son[i])
				printf("  SPF node %d leaves %d subnets\n",i,son[i]+1);   //+1,因為還和它的父親結點連接配接
		}
	}
}
int main(){	
	T = 0;
	while(Init()){
		Tarjain();	
		solve();
	}
}