hdu4587-TWO NODES(割点)

#include <bits/stdc++.h>
using namespace std;

const int N = 5005;
const int M = 100010;

struct Edge {
    int to, next;
} edge[M];
int head[N];
int cntE;
void addedge(int u, int v) {
    edge[cntE].to = v; edge[cntE].next = head[u]; head[u] = cntE++;
    edge[cntE].to = u; edge[cntE].next = head[v]; head[v] = cntE++;
}

int dfn[N], low[N], idx;
int stk[N], top;
bool cut[N];
int block[N];
// 一个割点可能在很多个连通分量
// 如果一个双连通分量内的某些顶点在一个奇圈中(即双连通分量含有奇圈
//  那么这个双连通分量的其他顶点也在某个奇圈中
// 如果一个双连通分量含有奇圈,则他必定不是一个二分图。反过来也成立,这是一个充要条件。
int no;
// block[i] 是去掉i这个节点能够多几个联通块
void tarjan(int u, int fa) {
    dfn[u] = low[u] = ++idx;
    stk[top++] = u;
    block[u] = 0;
    int son = 0;
    for (int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].to;
        if (v == fa || v == no) continue;
        if (!dfn[v]) {
            son++;
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (u != fa && low[v] >= dfn[u]) {
                cut[u] = true;
                block[u]++;
            }
            /* 求每一个连通分量
            if (low[v] >= dfn[u]) {

                int x;
                do {
                    x = stk[--top];
                    push(x);
                } while (x != v);
                push(u);
            }
            */
        } else {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if (u == fa) {
        if (son > 1) cut[u] = 1;
        block[u] = son-1;
    }
}


void init() {
    memset(dfn, 0, sizeof dfn);
    top = idx = cntE = 0;
}

int main()
{
    int n, m;
    while (~scanf("%d%d", &n, &m)) {
        int u, v;
        memset(head, -1, sizeof head);
        for (int i = 0; i < m; ++i) {
            scanf("%d%d", &u, &v);
            addedge(u, v);
        }
        int ans = 0;
        for (u = 0; u < n; ++u) {
            init(); int cnt = 0; no = u;
            for (v = 0; v < n; ++v) {
                if (v != u && !dfn[v]) {
                    tarjan(v, v);
                    cnt++;
                }
            }
            for (v = 0; v < n; ++v) {
                if (v != u) ans = max(ans, cnt + block[v]);
            }
        }
        printf("%d
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wenruo/p/5884617.html