zoukankan      html  css  js  c++  java
  • 洛谷 P3388 【模板】割点(割顶)(tarjan割点模板)

    题目背景

    割点
    题目描述

    给出一个n个点,m条边的无向图,求图的割点。
    输入输出格式
    输入格式:

    第一行输入n,m

    下面m行每行输入x,y表示x到y有一条边

    输出格式:

    第一行输出割点个数

    第二行按照节点编号从小到大输出节点,用空格隔开

    输入输出样例
    输入样例#1:

    6 7
    1 2
    1 3
    1 4
    2 5
    3 5
    4 5
    5 6

    输出样例#1:

    1
    5

    说明

    对于全部数据,n≤20000
    m≤100000

    点的编号均大于000小于等于nnn。

    tarjan图不一定联通。
    (模板,详情看注释)

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn=2e4+10;
    vector <int> ve[maxn];
    int cut[maxn],dfn[maxn],cnt,ans[maxn];
    int tarjan(int u,int fa)
    {
    	//记录有几个孩子,根节点有至少两个孩子才算割点。 
    	int child=0;
    	int lowu=dfn[u]=++cnt;
    	for(int i=0;i<ve[u].size();i++)
    	{
    		int v=ve[u][i];
    		if(!dfn[v])
    		{
    			child++;
    			//求孩子v子树上的最小的low 
    			int lowv=tarjan(v,u); 
    			lowu=min(lowu,lowv);
    			//如果lowv>dfn[u],说明v没有指向u祖先的点,说明u是割点 
    			if(lowv>dfn[u])
    			{
    			  cut[u]=1; 	
    			}	
    		}
    		else if(v!=fa)
    		{
    			//求u子树上的最小的low 
    		    lowu=min(lowu,dfn[v]);	
    		}
    		
    	}
    	//根节点有至少两个孩子才算割点
    	if(fa==0&&child<=1)
    	  cut[u]=0;
    	return lowu;
    	
    }
    int main(void)
    {
    	int n,m;
    	scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
        	int u,v;
        	scanf("%d%d",&u,&v);
        	ve[u].push_back(v);
        	ve[v].push_back(u);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		if(!dfn[i])
    		 tarjan(i,0);			  
    	}
    	int c=0;
    	for(int i=1;i<=n;i++)
    	   if(cut[i]) ans[c++]=i;
    	printf("%d
    ",c);
    	for(int i=0;i<c;i++)
    	  printf("%d%c",ans[i],i==c-1?'
    ':' ');
    	
    	return 0;
    }
    
  • 相关阅读:
    我心飞翔
    又见草堂
    有一种爱只能用心去珍藏《转贴》
    人事管理制度(爆笑)
    廊桥放歌
    记住: 惰性,职业生涯的无形杀手
    职场“三无人员”如何突破自己
    升职“流产”,都是谦虚惹的祸(转)
    李嘉诚让员工忠诚的简单办法
    尤未尽意
  • 原文地址:https://www.cnblogs.com/qinjames/p/10554940.html
Copyright © 2011-2022 走看看