HDU

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.

InputThe 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.OutputFor 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

题意:
问删除两个点后最大的联通块个数
思路:
没想到是一个暴力题,看了一下数据范围才反应过来.
题目既然要删除两个点,那就先枚举删除第一个点,再用割点判断第二个点删除后的联通块个数即可.
当然,有几点要注意一下:
1.联通块中点的个数全为1:
数据: 8 0
2.联通块中没有割点
 数据:
  3 3
  0 1
  0 2
  1 3

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>

#define fuck(x) cerr<<#x<<" = "<<x<<endl;
#define debug(a, x) cerr<<#a<<"["<<x<<"] = "<<a[x]<<endl;
#define ls (t<<1)
#define rs ((t<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100086;
const int maxm = 100086;
const int inf = 0x3f3f3f3f;
const ll Inf = 999999999999999999;
const int mod = 1000000007;
const double eps = 1e-6;
const double pi = acos(-1);

int Head[maxn], cnt;
struct edge {
    int Next, v;
} e[maxm];

void add_edge(int u, int v) {
    e[cnt].Next = Head[u];
    e[cnt].v = v;
    Head[u] = cnt++;
}

int Index = 0;
int dfn[maxn], low[maxn], root;
int vis[maxn];

int exc;
int ans;
int flag;
void dfs(int cur, int father) {
    if(cur==exc){ return;}
    flag++;
    int child = 0;
    Index++;
    dfn[cur] = Index;
    low[cur] = Index;
    for (int k = Head[cur]; k != -1; k = e[k].Next) {
        if(e[k].v==exc){ continue;}
        if (dfn[e[k].v] == 0) {
            child++;
            dfs(e[k].v, cur);
            low[cur] = min(low[cur], low[e[k].v]);
            if (cur != root && low[e[k].v] >= dfn[cur]) {
                vis[cur]++;
            }
            if (cur == root && child >= 2) {
                vis[cur]++;
            }
        } else if (e[k].v != father) {
            low[cur] = min(low[cur], dfn[e[k].v]);
        }
    }
}


int main() {
//    ios::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);

    int n,m;
    while (scanf("%d%d",&n,&m)!=EOF) {
        memset(Head, -1, sizeof(Head));
        cnt=0;
        for (int i = 1; i <= m; i++) {
            int x, y;
            scanf("%d%d", &x, &y);
            add_edge(x + 1, y + 1);
            add_edge(y + 1, x + 1);
        }

        int mx = 0;
        for (int i = 1; i <= n; i++) {
            exc = i;
            ans = 0;
            memset(vis, 0, sizeof(vis));
            memset(dfn, 0, sizeof(dfn));
            Index=0;
            dfn[exc]=-1;
            int tmp = -1;
            for (int j = 1; j <= n; j++) {
                if (!dfn[j] && j != i) {
                    root = j;
                    flag=0;
                    dfs(j, j);
                    if(flag>1){
                        tmp=0;//如果联通块内只有一个点,那么删除这个点之后,会使联通块少一
                        //所以至少保证有一个联通块内部包含了两个点,否则答案要减一
                    }
                    ans++;//已有的联通块
                }
            }

            for (int j = 1; j <= n; j++) {
                if(vis[j])tmp=max(tmp,vis[j]);//删去割点之后,可以获得的联通块
            }
            mx = max(ans+tmp, mx);
        }
        printf("%d
", mx );
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/ZGQblogs/p/11194806.html