avatar
fireworks99
keep hungry keep foolish

POJ 1144 Network(双连通+割点)

割点

将这个点去掉,图就会被分成两个部分(或者以上),那么这个点就是一个割点

判断割点

  1. 对根节点u,若其有两棵或两棵以上的子树,则该根结点u为割点;
  2. 对非叶子节点u(非根节点),若其子树的节点均没有指向u的祖先节点的回边,说明删除u之后,根结点与u的子树的节点不再连通;则节点u为割点。

POJ 1144 Network(求割点个数)

#include <stack> #include <vector> #include <stdio.h> #include <cstring> #include <iostream> #include <algorithm> using namespace std; bool flag[105]; int ans, cnt, low[105], time[105]; vector<int> v[105]; void init() { ans = cnt = 0; memset(flag, 0, sizeof(flag)); memset(low, 0, sizeof(low)); memset(time, 0, sizeof(time)); for(int i = 0; i <= 104; ++i) v[i].clear(); } void Trajan(int x, int pre) { int tem, sum = 0; low[x] = time[x] = ++cnt; for(int i = 0; i < v[x].size(); ++i) { tem = v[x][i]; if(!time[tem]) { Trajan(tem, x); low[x] = min(low[x], low[tem]); sum++; if(x != pre && low[tem] >= time[x]) flag[x] = 1; if(x == pre && sum > 1) flag[x] = 1; } else low[x] = min(low[x], time[tem]); } } int main() { int n; while(~scanf("%d", &n) && n) { init(); int u, to; while(~scanf("%d", &u) && u) { getchar(); char ch; while(1) { scanf("%d%c", &to, &ch); v[u].push_back(to); v[to].push_back(u); if(ch == '\n') break; } } Trajan(1, 1); // for(int i = 1; i <= n; ++i) // if(!time[i]) // Trajan(i, i); for(int i = 1; i <= n; ++i) if(flag[i]) ans++; cout << ans << '\n'; } return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76

割点可能被重复标记,所以不能在找到割点时计数

而必须找出所有割点再数出个数

Site by Baole Zhao | Powered by Hexo | theme PreciousJoy