题目大意:求无向图中的割点数目;
题目解析:用tarjan dfs的时候,如果枚举到某一边(u,v)其中low[v]>=dfn[u],就暂时设置is[u]=1最后枚举完的时候要判断这个点是否为根节点,如果是根节点并且儿子数目<=1,那么就不是割点;
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
using namespace std;
const int N=10010;
const int M=100010;
vector<int>vec[N];
bool is[N];
int low[N],dfn[N],cnt,ans;
void tarjan(int u,int father)
{
int i,v,child=0;
low[u]=dfn[u]=cnt++;
for(i=0;i<vec[u].size();i++)
{
v=vec[u][i];
if(u==v) continue;
if(dfn[v]==-1)
{
child++;
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
is[u]=1;
}
else if(father!=v)
low[u]=min(low[u],dfn[v]);
}
if(father<0&&child<=1) is[u]=0;;
}
int main()
{
int cas,c,i,n,k,u,v,j,m;
scanf("%d",&cas);
for(c=1;c<=cas;c++)
{
for(i=0;i<N;i++)
vec[i].clear();
cnt=0;
ans=0;
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
u--;
v--;
vec[u].push_back(v);
vec[v].push_back(u);
}
memset(dfn,-1,sizeof(dfn));
memset(low,-1,sizeof(low));
memset(is,0,sizeof(is));
for(i=0;i<n;i++)
{
if(dfn[i]==-1)
{
tarjan(i,-1);
}
}
for(i=0;i<n;i++)
{
if(is[i])
ans++;
}
printf("Case %d: %d\n", c,ans);
}
return 0;
}