5524 割点

5524 割点

 

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
 
 
 
题目描述 Description

给你一个图,这个图本身可能不是连通的,你要做的是求出图中所有连通分量中割点的总和。

输入描述 Input Description

第一行两个正整数N M,表示图有N个顶点,M条边,

接下来M行,每行两个整数a b,表示a,b之间有一条双向边。

输出描述 Output Description

输出一共包括一行,表示每个分量中割点的总和。

样例输入 Sample Input

5 5 

1 2 

2 3 

4 3 

4 5 

2 5

 

样例输出 Sample Output

1

数据范围及提示 Data Size & Hint

样例如图所示,唯一的割点为点2。

对于30%的数据,n,m<=101;

对于100%的数据,n,m<=15001;

分类标签 Tags 点此展开 

 求割点的模板

原理:传送门

AC代码:

 

#include<cstdio>
#include<vector>
using namespace std;
const int N=1e5+10;
struct node{
    int v,next;
}e[N<<1];int tot;
int n,m,pd,kid,head[N],dfn[N],low[N],fa[N],ans;
bool cut[N],mark[N];
void add(int x,int y){
    e[++tot]=(node){y,head[x]};
    head[x]=tot;
}
void tarjan(int x){
    dfn[x]=low[x]=++pd;
    int kid=0;bool flag=0;
    for(int i=head[x];i;i=e[i].next){
        int v=e[i].v;
        if(fa[x]!=v){
            if(!dfn[v]){
                kid++;
                fa[v]=x;
                tarjan(v);
                low[x]=min(low[x],low[v]);
                if(fa[x]!=-1&&low[v]>=dfn[x]) flag=1;
            }
            else low[x]=min(low[x],dfn[v]);
        }
    }
    if((fa[x]==-1&&kid>1)||flag) cut[x]=1;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int x,y,i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) fa[i]=-1,tarjan(i);
    for(int i=1;i<=n;i++) if(cut[i]) ans++;
    printf("%d",ans);
    return 0;
}

 

 

 

posted @ 2016-11-08 21:18  神犇(shenben)  阅读(201)  评论(0编辑  收藏  举报