题意: 输入一个无向图,求割点的数量。
题解: 模板题,注意输入就可以了,剩下的套模板就能解决。
- 定理一:T的根节点s是割点,当且仅当s有两个或更多的子节点。
- 定理二:T的非根节点u是割点,当且仅当u存在一个子节点v,v及其后代都没有会蜕变连回u的祖先。
定义num[]
记录DFS对每个点的访问顺序,num随着递推深度的增加而变大。
定义low[]
,记录v和v后代能连回到的祖先的num。
tarjan求割点
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N = 110;
int n, ans, dfn;
int num[N], low[N];
bool iscut[N];
vector<int> G[N];
void init(){
ans = dfn = 0;
for(int i = 0; i < N; i++) num[i] = low[i] = iscut[i] = 0, G[i].clear();
}
void read(){
int x, y;
while(~scanf("%d", &x) && x){
while(getchar() != '\n'){
scanf("%d", &y);
G[x].push_back(y);
G[y].push_back(x);
}
}
}
void dfs(int u, int fa){
low[u] = num[u] = ++dfn;
int child = 0;
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if(!num[v]){
child++;
dfs(v, u);
low[u] = min(low[u], low[v]);
if(low[v] >= num[u] && u != 1) iscut[u] = true;//
}else if(num[v] < num[u] && v != fa)
low[u] = min(low[u], num[v]);
}
if(u == 1 && child > 1) iscut[1] = true;
}
int main(){
while(~scanf("%d", &n) && n){
init();
read();
dfs(1, -1);
for(int i = 1; i <= n; i++) ans += iscut[i];
printf("%d\n", ans);
}
return 0;
}
把程序中的if(low[v] >= num[u] && u != 1)
改为if(low[v] > num[u] && u != 1)
,其他程序不变,就是求割边的数量。