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.
题目大意:给一个n个点m条边的无向图,删掉任意两个点,求最大联通分量数。
思路:枚举要被删掉的第一个点,然后用tarjan求剩下的每一个点被删掉后能增加的联通分量数。根据dfs的性质,有多少个分支的lowu ≥ pre[u],删掉u后就有多少个联通分量,删掉第一个点的时候剩下的块数加上删掉第二个点的联通分量数,就是删掉第一个点可以获得的最大连通分量数。要注意的是,如果要删掉的点是一个孤立的点,那么它的连通分量数反而会减少。时间复杂度为O(nm),12S可以承受。
代码(5000MS):

1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 using namespace std; 6 7 const int MAXN = 5010; 8 const int MAXE = MAXN * 2; 9 10 int head[MAXN]; 11 int to[MAXE], next[MAXE]; 12 int pre[MAXN], cut[MAXN]; 13 int n, m, dfs_clock, ecnt, stab; 14 15 void init() { 16 memset(head, 0, sizeof(head)); 17 ecnt = 1; 18 } 19 20 void add_edge2(int u, int v) { 21 to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++; 22 to[ecnt] = u; next[ecnt] = head[v]; head[v] = ecnt++; 23 } 24 25 int del; 26 27 int dfs(int u, int fa) { 28 int lowu = pre[u] = ++dfs_clock; 29 for(int p = head[u]; p; p = next[p]) { 30 int &v = to[p]; 31 if(v == del) continue; 32 if(!pre[v]) { 33 int lowv = dfs(v, u); 34 lowu = min(lowu, lowv); 35 if(lowv >= pre[u]) ++cut[u]; 36 } else if(pre[v] < pre[u] && v != fa) { 37 lowu = min(lowu, pre[v]); 38 } 39 } 40 if(fa < 0) --cut[u]; 41 return lowu; 42 } 43 44 int main() { 45 while(scanf("%d%d", &n, &m) != EOF) { 46 init(); 47 while(m--) { 48 int a, b; 49 scanf("%d%d", &a, &b); 50 add_edge2(a, b); 51 } 52 stab = 0; 53 for(int i = 0; i < n; ++i) { 54 del = i; 55 int sum = 0; 56 memset(pre, 0, sizeof(pre)); 57 memset(cut, 0, sizeof(cut)); 58 dfs_clock = 0; 59 for(int u = 0; u < n; ++u) { 60 if(u == i || pre[u]) continue; 61 ++sum; 62 dfs(u, -1); 63 } 64 int maxcut = -1; 65 for(int u = 0; u < n; ++u) if(u != i) 66 maxcut = max(maxcut, cut[u]); 67 stab = max(stab, sum + maxcut); 68 } 69 printf("%d ", stab); 70 } 71 }