#include<stdio.h>
#include<string.h>
#include<vector>
#define min(x,y)(x<y?x:y)
using namespace std;
vector<int>e[10010];
int time;
int low[10010];
int dfn[10010];
int cut[10010];
int n;
int k=0;
void find(int father,int u)
{
int son=0,cnt=0;
dfn[u]=low[u]=++time;
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i];
if(v==father&&cnt==0) //不在使用之前用过的边
{
cnt++;
continue;
}
if(dfn[v]==-1)
{
son++; //记录子树个数
find(u,v);
low[u]=min(low[v],low[u]);
if(father==0&&son>1) //如果是头结点并且子树不止一个则该点是割点
{
cut[u]=1;
}
if(father!=0&&dfn[u]<=low[v]) //如果不是头结点,并且子节点v无法遍历到u的父节点,则说明u为割点
{
cut[u]=1;
}
}
else
{
low[u]=min(dfn[v],low[u]);
}
}
}
int cut_point_sum()
{
int res=0;
time=0;
memset(dfn,-1,sizeof(dfn));
memset(cut,-1,sizeof(cut));
for(int i=1;i<=n;i++)
{
if(dfn[i]==-1)
{
find(0,i);
}
}
for(int i=1;i<=n;i++)
{
if(cut[i]==1)
res++;
}
return res;
}
int main()
{
int t,i,m,u,v;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
e[i].clear();
}
for(i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
int res=cut_point_sum();
printf("Case %d: %d\n",++k,res);
}
return 0;
}
/*
3
5 4
2 1
1 3
5 4
4 1
3 3
1 2
2 3
1 3
4 4
1 2
3 2
3 4
4 1
*/
LightOJ - 1063Ant Hills 无向图割点
最新推荐文章于 2022-11-01 17:13:14 发布