POJ1144 Network 题解 点双连通分量(求割点数量)

题目链接:http://poj.org/problem?id=1144

题目大意:给以一个无向图,求割点数量。

这道题目的输入和我们一般见到的不太一样。
它首先输入 \(N\)(\(\lt 100\))表示点的数量(\(N=0\)表示文件输入结束)。
然后接下来每行输入一组数字。

  • 如果这一组数字只包含一个 \(0\) ,说明本组测试数据输入结束;
  • 否则,假设这些数可以拆分成 \(a_1,a_2,a_3, \cdots ,a_m\),则说明 \(a_1\) 这个点到 \(a_2,a_3, \cdots , a_m\) 之间都存在着一条边。

所以这道题目想要表达的意思还是一样的 \(\Rightarrow\) 求割点的数量,只不过输入方式和我们平时见到的不太一样。

观察DFS搜索树,我们可以发现有两类节点可以成为割点:

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

实现代码如下:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <cstdio>
using namespace std;
const int maxn = 10010;
int n, m, dfn[maxn], low[maxn], f[maxn], cnt, ans;
bool vis[maxn];
vector<int> g[maxn];
void init() {
    ans = cnt = 0;
    for (int i = 1; i <= n; i ++) {
        low[i] = dfn[i] = f[i] = vis[i] = 0;
        g[i].clear();
    }
}
void tarjan(int u) {
    low[u] = dfn[u] = ++cnt;
    int son_num = 0;    // 记录子树数量
    int sz = g[u].size();
    for (int i = 0; i < sz; i ++) {
        int v = g[u][i];
        if (!dfn[v]) {  // v未被访问,(u,v)为树边
            son_num ++;
            f[v] = u;
            tarjan(v);
            low[u] = min(low[u], low[v]);
            if (dfn[u] == 1 && son_num > 1 && !vis[u]) {    // 根节点,子树数量大于1即为割点
                vis[u] = true;
                ans ++;
            }
            else if (dfn[u] != 1 && low[v] >= dfn[u] && !vis[u]) {  // 其余节点子树可追溯到最早的祖先节点要么为v要么为u
                vis[u] = true;
                ans ++;
            }
        }
        else if (f[v] != u) {   // 节点v已被访问,则(u,v)为回边
            low[u] = min(low[u], dfn[v]);
        }
    }
}
int main() {
    while (~scanf("%d", &n) && n) {
        init();
        getchar();
        string s;
        int a, b;
        while (getline(cin, s)) {
            stringstream ss(s);
            ss >> a;
            if (!a) break;
            while ((ss >> b) && b) {
                g[a].push_back(b);
                g[b].push_back(a);
            }
        }
        tarjan(1);
        cout << ans << endl;
    }
    return 0;
}

参考链接:

原文地址:https://www.cnblogs.com/quanjun/p/12134151.html

时间: 2024-11-08 20:03:07

POJ1144 Network 题解 点双连通分量(求割点数量)的相关文章

poj 1144 Network【双连通分量求割点总数】

Network Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11042   Accepted: 5100 Description A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places numbered by integers from 1 to N

hdoj 4738 Caocao&#39;s Bridges【双连通分量求桥】

Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3000    Accepted Submission(s): 953 Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. Bu

POJ 1144 Network(无向图连通分量求割点)

题目地址:POJ 1144 求割点.推断一个点是否是割点有两种推断情况: 假设u为割点,当且仅当满足以下的1条 1.假设u为树根,那么u必须有多于1棵子树 2.假设u不为树根.那么(u,v)为树枝边.当Low[v]>=DFN[u]时. 然后依据这两句来找割点就能够了. 代码例如以下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include &

zoj 2588 Burning Bridges【双连通分量求桥输出桥的编号】

Burning Bridges Time Limit: 5 Seconds      Memory Limit: 32768 KB Ferry Kingdom is a nice little country located on N islands that are connected by M bridges. All bridges are very beautiful and are loved by everyone in the kingdom. Of course, the sys

tarjan双联通求割点和桥模板

  求割点 int n,m,stamp,low[1005],dfn[1005],iscut[1005];//iscut记录的为割点 vector<int> vec[1005]; void tarjan(int index,int fa){ int child=0; low[index]=dfn[index]=++stamp; for(int i=0;i<vec[index].size();i++) { int tmp=vec[index][i]; if(!dfn[tmp]) { chil

hdoj 4612 Warm up【双连通分量求桥&amp;&amp;缩点建新图求树的直径】

Warm up Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 5093    Accepted Submission(s): 1131 Problem Description N planets are connected by M bidirectional channels that allow instant transport

fzu2181(点的双连通分量+求奇环)

求出每个点双连通分量,如果在一个点双连通分量中有奇环,则这个分量每个点都在一个奇环中.  关键是要知道怎么求点双连通分量以及点双连通的性质. fzu2181 http://acm.fzu.edu.cn/problem.php?pid=2181 #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define

poj 1144 (Tarjan求割点数量)

题目链接:http://poj.org/problem?id=1144 描述 一个电话线公司(简称TLC)正在建立一个新的电话线缆网络.他们连接了若干个地点分别从1到N编号.没有两个地点有相同的号码.这些线是双向的并且能使两个地点保持通讯.每个地点的线都终结于电话交换机.每个地点都有一个电话交换机.从每个地点都能通过线缆到达其他任意的地点,然而它并不需要直接连接,它可以通过若干个交换机来到达目的地.有时候某个地点供电出问题时,交换机就会停止工作.TLC的工作人员意识到,除非这个地点是不可达的,否

UVA - 315 Network(tarjan求割点的个数)

题目链接:https://vjudge.net/contest/67418#problem/B 题意:给一个无向连通图,求出割点的数量.首先输入一个N(多实例,0结束),下面有不超过N行的数,每行的第一个数字代表后面的都和它存在边,0表示行输入的结束. 题解:简单的求割点模版,所谓割点就是去掉这一个点还有于这个点链接的边之后使得原来的图连通块增加. 由于这是模版题代码会加上注释. #include <iostream> #include <cstring> using namesp