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