HDU 4587 (割点)

TWO NODES

Time Limit: 24000/12000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1618    Accepted Submission(s): 502


Problem Description
Suppose that G is an undirected graph, and the value of  stab is defined as follows:

Among the expression,G -i, -j is the remainder after removing node i, node j and all edges that are directly relevant to the previous two nodes.  cntCompent is the number of connected components of X independently.
Thus, given a certain undirected graph G, you are supposed to calculating the value of  stab.
 

Input
The input will contain the description of several graphs. For each graph, the description consist of an integer N for the number of nodes, an integer M for the number of edges, and M pairs of integers for edges (3<=N,M<=5000).
Please note that the endpoints of edge is marked in the range of [0,N-1], and input cases ends with EOF.
 

Output
For each graph in the input, you should output the value of  stab.
 

Sample Input
 
   
4 5 0 1 1 2 2 3 3 0 0 2
 

Sample Output
 
   
2
 


题意:求一个图去掉两个点之后的最多的联通分量数.

首先枚举一个去掉的点,然后求出所有的割点,对于所有的割点,他能够遍历到的点并

且没有访问过的点数就是删去他能够增加的联通分量数.

坑点:

注意树根和孤立节点的情况.

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 5111;
const int maxm = 11111;
typedef long long ll;

int n, m;
struct node {
    int u, v, next;
}edge[maxm];
int head[maxn], cnt;

void add_edge (int u, int v) {
    edge[cnt].u = u, edge[cnt].v = v, edge[cnt].next = head[u], head[u] = cnt++;
}

int dfs_clock, pre[maxn], low[maxn], cur, ans;
bool is_cut[maxn];

int dfs (int u, int fa, int del) {
    int lowu = pre[u] = ++dfs_clock;
    int child = 0, curnum = 0;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        int v = edge[i].v;
        if (v == del)//删掉的点
            continue;
        if (!pre[v]) {
            child++;
            int lowv = dfs (v, u, del);
            lowu = min (lowu, lowv);
            if (lowv >= pre[u]) {
                is_cut[u] = 1;
                curnum++;
            }
        }
        else if (pre[v] < pre[u] && v != fa) {
            lowu = min (lowu, pre[v]);
        }
    }
    if (fa < 0 && child == 1) {
        is_cut[u] = 0;
    }
    if (child == 0 && fa < 0) {
        ans = max (ans, cur-1);
    }
    if (is_cut[u])
        ans = max (ans, cur+curnum-(fa<0));
    low[u] = lowu;
    return lowu;
}

int cc = 0;
bool vis[maxn];
void go (int u, int fa, int del) {
    cc++;
    vis[u] = 1;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        int v = edge[i].v;
        if (v == fa || vis[v] || v == del)
            continue;
        go (v, u, del);
    }
}

int main () {
    //freopen ("in.txt", "r", stdin);
    while (scanf ("%d%d", &n, &m) == 2) {
        memset (head, -1, sizeof head);
        cnt = 0;
        for (int i = 1; i <= m; i++) {
            int u, v;
            scanf ("%d%d", &u, &v);
            add_edge (u, v);
            add_edge (v, u);
        }
        ans = 0;
        for (int i = 0; i < n; i++) {//枚举删掉的点
            dfs_clock = 0;
            memset (is_cut, 0, sizeof is_cut);
            memset (pre, 0, sizeof pre);
            int u;
            cur = 0;
            memset (vis, 0, sizeof vis);
            bool ok = 0;
            for (u = 0; u < n; u++) if (!vis[u] && u != i) {
                cc = 0;
                go (u, -1, i);
                cur++;
                if (cc > 1)
                    ok = 1;
            }
            if (cur == n-1) {
                ans = max (ans, n-2);
                continue;
            }
            if (ok) {
                ans = max (ans, cur);
            }
            for (u = 0; u < n; u++) if (!pre[u] && u != i) {
                dfs (u, -1, i);//找到所有的割点
            }
        }
        printf ("%d\n", ans);
    }
    return 0;
}


你可能感兴趣的:(连通性)