• 割点和割边


    关于割点的详细讲解见这篇文章

    //时间复杂度:O(N+M) 
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=20010;
    int N, M, bj[maxn], ans=0, dfn[maxn], low[maxn], fa[maxn], timestamp=0; 
    struct edge{ int t; edge *nxt; edge(int to, edge *next){t=to, nxt=next; } };
    edge *h[maxn];
    void add(int u, int v){ h[u]=new edge(v, h[u]); h[v]=new edge(u, h[v]); }	//add一次加两条边,无向图 
    
    void tarjan(int x)
    { 
    	dfn[x]=low[x]=++timestamp;
    	int child=0;															//child为结点的子树数量 
    	for(edge *p=h[x]; p; p=p->nxt)
    	{
    		if(p->t==fa[x])	continue;											//不能往父亲方向走 
    		if(dfn[p->t])	low[x]=min(low[x], low[p->t]);						//发现返祖边,更新low值 
    		else
    		{
    			fa[p->t]=x; 
    			tarjan(p->t);
    			low[x]=min(low[x], low[p->t]);
    			if(fa[x]!=0 && low[p->t]>=dfn[x]) bj[x]=1;						//x不是根结点,且其孩子的low值>=其dfn值,x为割点 
    			if(fa[x]==0)	child++;										//如果x是根结点,在此情况下发现其一颗子树 
    		    if(low[p->t]>=dfn[x])    记录这条边(x, p->t);                   //判断割边(桥)就这么简单,自己意会吧……
            }
    	}
    	if(fa[x]==0 && child>=2)	bj[x]=1;									//如果x是根结点且子树>=2,x为割点 
    }
    
    int main()
    {
    	scanf("%d%d", &N, &M);
    	for(int i=1, x, y; i<=M; i++)		scanf("%d%d", &x, &y), add(x, y);
    	for(int i=1; i<=N; i++)													//考虑原图可能是非连通的 
    		if(!dfn[i])	tarjan(i);
    	for(int i=1; i<=N; i++)	if(bj[i])	ans++;								//统计割点个数 
    	printf("%d
    ", ans);
    	for(int i=1; i<=N; i++)	if(bj[i])	printf("%d ", i);					//由小到大输出割点 
    	return 0;
    }
    
  • 相关阅读:
    jquery获取select选中的文本值
    Nginx实战入门教程
    【分享】Jenkins自动化部署全套视频教程
    Jenkins自动化部署入门详细教程
    【分享】nginx负载均衡全套视频教程
    IT从业者疫情之下出路何在
    jmeter控制器(四)
    jmeter控制器(三)
    复述记忆法的初步学习总结
    raspberry-gpio-python(树莓派GPIO与Python编程)
  • 原文地址:https://www.cnblogs.com/lfyzoi/p/10682301.html
Copyright © 2020-2023  润新知