zoukankan      html  css  js  c++  java
  • [笔记][题解]割点&lgP3388

    [笔记][题解]割点&lgP3388

    原题链

    割点的概念

    在无向连通图中,如果将其中一个点以及所有连接该点的边去掉,图就不再连通,那么这个点就叫做割点.

    解题方法

    这个题我们用类似于缩点的方法,定义(dfn)(low)数组,(dfn)指的是(dfs)序,(low[x])指的是(x)节点不通过父亲节点所能到达的(dfn)值最小的点.对于根节点,如果它有两个及以上的子树,那么它就是割点,因为如果没有了根节点,子树与子树之间就不能相连;对于非根节点(x),就用(dfn[x])的值和它所有儿子节点的(low)值相比,如果存在有(low[son] ≥ dfn[x])则说明(x)就是割点,因为(x)有某个儿子必须通过它才能到达(x)的祖先节点;对于没有儿子的节点,它显然不会是割点.

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int n,m;
    struct node{
    	int to,next;
    }edge[1000010 * 2];
    int fir[1000010],tot,root;
    void add(int x, int y){
    	edge[++tot].to = y;
    	edge[tot].next = fir[x];
    	fir[x] = tot;
    }
    int dfn[1000010],low[1000010],cnt;
    bool is[1000010];
    void tarjan(int x){
    	dfn[x] = low[x] = ++cnt;
    	int flag = 0;
    	for(int i = fir[x];i;i = edge[i].next){
    		if(!dfn[edge[i].to]){
    			tarjan(edge[i].to);
    			low[x] = min(low[x],low[edge[i].to]);
    			if(low[edge[i].to] >= dfn[x]){
    				flag++;
    				if(flag >= 2 || x != root)
    					is[x] = 1;
    			}
    		}
    		else low[x] = min(low[x],dfn[edge[i].to]);
    	}
    }
    int main(){
    	cin>>n>>m;
    	for(int i = 1;i <= m;i++){
    		int x,y;
    		cin>>x>>y;
    		add(x,y);add(y,x);
    	}
    	for(int i = 1;i <= n;i++){
    		if(!dfn[i]){
    			root = i;
    			tarjan(i);
    		}
    	}
    	int ans = 0;
    	for(int i = 1;i <= n;i++)
    		if(is[i])
    			ans++;
    	cout<<ans<<endl;
    	for(int i = 1;i <= n;i++)
    		if(is[i])
    			cout<<i<<" ";
    	cout<<endl;
    	return 0;
    }
    
  • 相关阅读:
    KMP
    图论知识,博客
    POJ 2318/2398 叉积性质
    CF821 E. Okabe and El Psy Kongroo 矩阵快速幂
    CF821 D. Okabe and City 图 最短路
    CF821 C. Okabe and Boxes 栈模拟
    CF821 A. Okabe and Future Gadget Laboratory 水
    Atcoder arc077 D
    Atcoder #017 agc017 D.Game on Tree 树上NIM 博弈
    Atcoder #017 agc017 B.Moderate Differences 思维
  • 原文地址:https://www.cnblogs.com/czy--blog/p/13902632.html
Copyright © 2011-2022 走看看