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