题目连接
题意:
让求一个图中的关键节点(割点),输入稍微有点麻烦,不给你一个点有几个边,直接输入边,读到换行才结束。
思路:
1)Tarjan求一下改图割点的数量。
2)注意输入读到换行才停止,用getchar()。点击补习读入方式
AC代码
/*
Tarjan 割点
//如果这个点时根节点,并且儿子>=2则这个点就是割点
//对于点U存在子节点V,V可以访问到U的父节点,那么点U就不是割点,否则就是割点
*/
#include<iostream>
#include<cstring>
#include<math.h>
#include<algorithm>
#include<stdio.h>
#include<stack>
#include<set>
using namespace std;
const int MAXN = 1e5;
int head[MAXN], cnt, tot, dfn[MAXN], low[MAXN];
int root;
int n, m;
set<int> ans;
struct Edge{
int to, dis, next;
}edge[MAXN << 1];
void add_edge(int u, int v, int dis) {
edge[++cnt].to = v;
edge[cnt].dis = dis;
edge[cnt].next = head[u];
head[u] = cnt;
}
void init() {
cnt = 1;
tot = 0;
memset(head, 0, sizeof(head));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
ans.clear();
}
void Tarjan(int x, int fa) {
low[x] = dfn[x] = ++tot;
int son = 0;
for (int i = head[x]; i; i = edge[i].next) {
int to = edge[i].to;
if(to == fa) continue; //因为是无向图所以把回边给跳过了
if (!dfn[to]) {
Tarjan(to, x);
low[x] = min(low[x], low[to]);
son++;
if ( x == root && son > 1) { //如果这个点时根节点,并且儿子>=2则这个点就是割点
ans.insert(x);
} else if (x != root && dfn[x] <= low[to] ) { //对于点U存在子节点V,V可以访问到U的父节点,那么点U就不是割点,否则就是割点
ans.insert(x);
}
} else {
low[x] = min(low[x], dfn[to]);
}
}
}
int main() {
while(scanf("%d", &n) == 1 && n) {
int u, v;
init();
while(scanf("%d", &u) == 1 && u) {
while(getchar()!='\n'){
scanf("%d", &v);
add_edge(u, v, 0);
add_edge(v, u, 0);
}
}
for (int i = 1; i <= n; ++i) {
if (!dfn[i]){
root = i;
Tarjan(i, i);
}
}
printf("%d\n", ans.size());
}
return 0;
}