引入
割点是指在无向图中,割去一个点,图不联通。
这种问题仍然用tarjan解决。
例题
分析
割点裸题
代码
#include<bits/stdc++.h>
using namespace std;
#define N 105
#define INF 0x3f3f3f3f
int dfn[N],low[N],num,root,spot[N];
int n,ans;
vector<int>adj[N];
void tarjan(int u,int dad){
dfn[u]=low[u]=++num;
int k=0;//记录子树
for(int i=0,sz=adj[u].size();i<sz;i++){
int v=adj[u][i];
if(!dfn[v]){
k++;tarjan(v,u);
low[u]=min(low[u],low[v]);
if(u!=root&&dfn[u]<=low[v]//u不是根结点&&v不能到u的上面
||u==root&&k>=2)spot[u]=1;//或u是根结点&&有多个子树
//u是割点
}
else if(v!=dad)//无向图,v必须不为父亲
low[u]=min(low[u],dfn[v]);
}
}
void init(){
num=0,ans=0;
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(spot,0,sizeof spot);
for(int i=1;i<=n;i++)adj[i].clear();//初始化
while(1){
int x=0;
char ch=getchar();
while(ch!=' '&&ch!='\n'){
x=10*x+ch-'0';
ch=getchar();
}
if(x==0)return;
int y=0;ch=getchar();
while(ch!='\n'){
if(ch!=' ')y=10*y+ch-'0';
else {
adj[x].push_back(y);
adj[y].push_back(x);
y=0;
}
ch=getchar();
}
adj[x].push_back(y);
adj[y].push_back(x);
}//getchar读入
}
int main(){
while(1){
scanf("%d",&n);
if(n==0)return 0;
scanf("\n");
init();
for(int i=1;i<=n;i++)
if(!dfn[i]){root=i;tarjan(i,i);}//对图的不联通处理
for(int i=1;i<=n;i++)
if(spot[i])ans++;//统计结点数
printf("%d\n",ans);
}
}