hdu 4587 TWO NODES (割点的应用)

TWO NODES

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


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


题意:n个点(编号0--n-1),m条边,问删除哪两个点使得图中连通分量最多,输出这个最多的分量个数。


做法:首先肯定和割点有关,删除一个的话可以删除关联连通分量最多的那个割点,但是删两个就有点无所适从了,因为不能贪心的删最多和次多的,会产生问题。那么,可以考虑枚举第一个点,去找第二个点。找第二个点就和删除一个点使得联通分量最多有点像了,不过需要注意的是,删除了第一个点之后图可以能是不连通的,找第二个点的时候必须要遍历整个图。具体细节看代码。


CODE

#include 
using namespace std;
const int N = 5000+10;
struct node{
    int v,next;
    node(){}
    node(int v,int next):
        v(v),next(next){}
}E[N*5];

int n,m,top;
int dfs_clock;      ///时间戳
int head[N];
int cnt[N];         ///点被删除后可以增加几个联通分量
int dfn[N],low[N];  ///Tarjan用
void Init()
{
    dfs_clock = 0;
    for(int i = 0;i < N;i++){
        cnt[i] = 1; ///删除某一个点必然会一个产生由它父亲而来联通分量
        dfn[i] = low[i] = 0;
    }
}
void add(int u,int v)
{
    E[top] = node(v,head[u]);
    head[u] = top++;
}

int Tarjan(int u,int ufa,int fa)
{
    dfn[u] = low[u] = ++dfs_clock;
    for(int i = head[u];i != -1;i = E[i].next){
        int v = E[i].v;
        if(v == ufa) continue;
        if(v == fa) continue;   ///跑到删除的那个点就不dfs了
        if(!dfn[v]){
            Tarjan(v,u,fa);
            low[u] = min(low[u],low[v]);
            if(low[v] >= dfn[u]) cnt[u]++; ///是割点
        }
        else
            low[u] = min(low[u],dfn[v]);
    }
}

int main(void)
{
    while(scanf("%d%d",&n,&m) != EOF){
        top = 0;
        memset(head,-1,sizeof head);
        for(int i = 1;i <= m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        int ans = 0;
        for(int i = 0;i < n;i++){       ///枚举删除的点
            Init();                     ///每次都要初始化
            cnt[i] = 0;
            int sum = 0;
            for(int j = 0;j < n;j++){   ///图不一定连通,所以要遍历每一个点看是否访问过
                if(i != j && !dfn[j]){
                    sum++;
                    cnt[j] = 0;
                    Tarjan(j,-1,i);
                }
            }
            for(int j = 0;j < n;j++){
                ans = max(ans,sum+cnt[j]-1); ///sum里面本身包含了这个连通分量,删除这个点产生cnt个分量,本身存在的连通分量应消失
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}





你可能感兴趣的:(图论__割点和桥)