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 <bits/stdc++.h>
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;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值