题目链接:1063 - Ant Hills
题目大意
一个n各节点m条边的无向图。让你求有多少个割点。
解题思路
直接利用 tarjon 求割点。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mx=10001;
int n,cnt,ans;
int dfn[mx],low[mx];
bool f[mx];
stack<int> st;
vector<int> ve[mx];
set<int> si;
void tarjon(int x,int fa){
dfn[x]=low[x]= ++cnt;
f[x]=1;
st.push(x);
int son=0;
for(int v: ve[x]){
if(v==fa) continue;
if(!dfn[v]){
tarjon(v,x);
// 求割点
low[x]=min(low[x],low[v]);
// 如果这节点是根节点,那么只要缩了点以后的儿子数量多于1就是个割点
if (fa==-1&&son!=0)
si.insert(x);
// 这里针对的是不是跟节点的节点如果其 dfn值
// 小于等于子节点low值的那么它肯定是割点
if (fa!=-1 && low[v]>=dfn[x])
si.insert(x);
son++;
}else if(f[v]){
low[x]=min(low[x],dfn[v]);
}
}
if(low[x]==dfn[x]){
int k;
do{
k=st.top();
st.pop();
f[k]=0;
}while(k!=x);
}
}
void init(){
si.clear();
while(!st.empty()) st.pop();
for(int i=1;i<=n;i++) dfn[i]=low[i]=f[i]=0,ve[i].clear();
cnt=ans=0;
}
int main(){
int t,m;cin>>t;
for(int ca=1;ca<=t;ca++){
cin>>n>>m;
for(int i=0,x,y;i<m;i++){
cin>>x>>y;
ve[x].push_back(y);
ve[y].push_back(x);
}
cout<<"Case "<<ca<<": ";
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjon(i,-1);
}
cout<<si.size()<<"\n";
init();
}
return 0;
}