zoukankan      html  css  js  c++  java
  • HDU 4587 TWO NODES(割点)(2013 ACM-ICPC南京赛区全国邀请赛)

    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 }
    View Code
  • 相关阅读:
    认识弹性盒子
    管理Linux服务器的用户和组(续篇)
    管理Linux服务器的用户和组
    centos7 mysql数据库安装和配置
    熟练使用Linux进程管理类命令
    熟练使用Linux系统信息类命令
    Linux操作系统-基本命令(二)
    Linux操作系统-基本命令(一)
    api接口统一封装
    10分钟,让你彻底明白Promise原理
  • 原文地址:https://www.cnblogs.com/oyking/p/3279514.html
Copyright © 2011-2022 走看看