判断给定的顶点是否是给定无向图的【割点】

割点的定义是,如果删除该顶
点后会使该无向图的连通分量(连通块)个数变多,那么就称该顶点为该无向图的割点。
求无向图的连通块个数的基本思路是,开一个 vis 数组表示顶点是否已访问,然后遍历所有
顶点,如果当前顶点还没有被访问,那么就访问该顶点所在的连通块,将该连通块中的所有顶
点都标记为已访问。而遍历连通块也只需要一个简单的 DFS 就能解决,书上 10.3 图的遍历这个
小节已经写得很清楚了。
至于删除顶点这个操作其实不必真的去删,只需要在 DFS 的时候判断一下是不是要被删掉
的这个顶点,是的话跳过这个顶点就行。

#include 
#include 
using namespace std;
const int MAXV = 1010;  // 顶点数上限
bool G[MAXV][MAXV];     // 无向图G
bool vis[MAXV];         // 顶点是否已被访问
int n, m, deletedIdx;   // 顶点数, 边数, 被删除的顶点编号
// 将顶点u所在的连通块里的顶点都标记为已访问
void DFS(int u) {
    for(int v = 1; v <= n; v++) {   // 遍历所有顶点
        // 如果顶点v不是被删除的顶点,且边u<->v存在,且v还没有被访问
        if(v != deletedIdx && G[u][v] && !vis[v]) {
            vis[v] = true;  // 标记顶点v为已访问
            DFS(v);         // 访问顶点v所在的连通块
        }
    }
}
// 计算连通块个数
int calSubGraphNumber() {
    memset(vis, false, sizeof(vis));    // 初始化所有顶点为未访问
    int num = 0;    // 连通块个数
    for(int i = 1; i <= n; i++) {   // 遍历所有顶点
        if(i != deletedIdx && !vis[i]) {    // 如果顶点i不是被删除的顶点,且i所在的连通块还没有被访问
            vis[i] = true;  // 标记顶点i为已访问
            DFS(i);         // 访问顶点i所在的连通块,将连通块中的所有顶点都标记为已访问
            num++;          // 连通块个数加1
        }
    }
    return num;     // 返回连通块个数
}
int main() {
    scanf("%d%d", &n, &m);  // 顶点数, 边数
    for(int i = 0; i < m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u][v] = G[v][u] = true;   // 无向图的边
    }
    int originSubGraphNumber = calSubGraphNumber();     // 计算未删点之前的连通块数量
    int k;
    scanf("%d", &k);    // 查询个数
    while(k--) {
        scanf("%d", &deletedIdx);   // 被删除的顶点编号
        int newSubGraphNumber = calSubGraphNumber();    // 计算删除顶点后的连通块数量
        if(newSubGraphNumber > originSubGraphNumber) {  // 如果连通块数量变多, 则输出YES, 否则输出NO
            printf("YES\n");
        } else {
            printf("NO\n");
        }
    }
    return 0;
}

你可能感兴趣的:(判断给定的顶点是否是给定无向图的【割点】)