学长写的:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define maxn 10005
int dfn[maxn];///代表最先遍历到这个点的时间
int low[maxn];///这个点所能到达之前最早的时间点
int Father[maxn];///保存这个节点的父亲节点
int n, m, Time, top;///Time 时间点, top用于栈操作
vector<vector<int> > G;
void Init()
{
G.clear();
G.resize(n+1);
memset(low, 0, sizeof(low));
memset(dfn, 0, sizeof(dfn));
memset(Father, 0, sizeof(Father));
Time = 0;
}
void Tarjan(int u,int fa)
{
low[u] = dfn[u] = ++Time;
Father[u] = fa;
int len = G[u].size(), v;
for(int i=0; i<len; i++)
{
v = G[u][i];
if(!dfn[v])
{
Tarjan(v, u);
low[u] = min(low[u], low[v]);
}
else if(fa != v)///假如我们在这里写上了 low[u] = min(low[v], low[u]),那么就相当于我们由v回到了v之前的节点
low[u] = min(dfn[v], low[u]);
}
}
void solve()
{/**
求割点
一个顶点u是割点,当且仅当满足(1)或(2)
(1) u为树根,且u有多于一个子树。
(2) u不为树根,且满足存在(u,v)为树枝边(或称 父子边,即u为v在搜索树中的父亲),使得 dfn(u)<=low(v)。
(也就是说 V 没办法绕过 u 点到达比 u dfn要小的点)
注:这里所说的树是指,DFS下的搜索树*/
int RootSon = 0, ans = 0;///根节点儿子的数量
bool Cut[maxn] = {false};///标记数组,判断这个点是否是割点
Tarjan(1,0);
for(int i=2; i<=n; i++)
{
int v = Father[i];
if(v == 1)///也是就说 i的父亲是根节点
RootSon ++;
else if(dfn[v] <= low[i])
Cut[v] = true;
}
for(int i=2; i<=n; i++)
{
if(Cut[i])
ans ++;
}
if(RootSon > 1)
ans++;
printf("%d\n", ans);
}
int main()
{
while(scanf("%d", &n), n)
{
int a, b;
char ch;
Init();
while(scanf("%d", &a), a)
{
while(scanf("%d%c",&b,&ch))
{
G[a].push_back(b);
G[b].push_back(a);
if(ch == ‘\n‘)
break;
}
}
solve();
}
return 0;
}
自己又写的
#include<iostream> #include<stdio.h> #include<string.h> #include<vector> #include<algorithm> using namespace std; #define N 110 #define min(a, b) a<b?a:b int n, father[N]; int visit[N], rode[N]; int rootson, ans, t, inter[N]; vector<vector<int> >G; void Init() { G.clear(); G.resize(n+1); rootson=0; ans=0; t=0; memset(inter, 0, sizeof(inter)); memset(visit, 0, sizeof(visit)); memset(rode, 0, sizeof(rode)); memset(father, 0, sizeof(father)); } void Tarjan(int u, int fu) { visit[u]=rode[u]=++t; father[u]=fu; int len=G[u].size(); for(int i=0; i<len; i++) { int v=G[u][i]; if(!visit[v]) { Tarjan(v, u); rode[u]=min(rode[u], rode[v]); } else if(v!=fu) { rode[u]=min(visit[v], rode[u]); } } } void solve() { Tarjan(1, 0); for(int i=2; i<=n; i++) { int v=father[i]; if(v==1) rootson++; else if(visit[v]<=rode[i])//这一点可能不理解吧 inter[v]=1; } for(int i=2; i<=n; i++) { if(inter[i]) ans++; } if(rootson>1) ans++; printf("%d\n", ans); } int main() { while(scanf("%d", &n), n) { Init(); int a, b; char ch; while(scanf("%d", &a), a) { while(scanf("%d%c", &b, &ch)!=EOF) { G[a].push_back(b); G[b].push_back(a); if(ch==‘\n‘) break; } } solve(); } return 0; }