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

    Description

      给出一个(n)个点,(m)条边的无向图,求图的割点。

    Input

      第一行输入(n),(m)
      下(m)行每行输入(x),(y)表示(x)(y)有一条边。

    Output

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

    Solution

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=20000,M=200000;
    int n,m,u,v,vis[N+10],cnt,cut[N+10],ans;
    int head[N+10],nxt[M+10],vet[M+10],low[N+10],dfn[N+10];
    inline int read()
    {
    	int ans=0;
    	char ch=getchar();
    	while (ch<'0' || ch>'9') ch=getchar();
    	while (ch>='0' && ch<='9')
    	{
    		ans=ans*10+ch-'0';
    		ch=getchar();
    	}
    	return ans;
    }
    void addedge(int u,int v)
    {
    	nxt[++cnt]=head[u];vet[cnt]=v;head[u]=cnt;
    }
    void tarjan(int u,int rt)
    {
    	vis[u]=1;low[u]=dfn[u]=++cnt;
    	int child=0;
    	for (int i=head[u];i;i=nxt[i])
    	{
    		int v=vet[i];
    		if (!vis[v])
    		{
    			tarjan(v,rt);child++;
    			low[u]=min(low[u],low[v]);
    			if (low[v]>=dfn[u] && u!=rt) ans+=cut[u]?0:1,cut[u]=1;
    			if (child>=2 && u==rt) ans+=cut[u]?0:1,cut[u]=1;
    		}
    		else low[u]=min(low[u],dfn[v]);
    	}
    }
    int main()
    {
    	n=read(),m=read();
    	for (int i=1;i<=m;i++)
    	{
    		int u=read(),v=read();
    		addedge(u,v);
    		addedge(v,u);
    	}
    	for (int i=1;i<=n;i++)
    		if (!vis[i]) tarjan(i,i);
    	printf("%d
    ",ans);
    	for (int i=1;i<=n;i++)
    		if (cut[i]) printf("%d ",i);
    	printf("
    ");
    	return 0;
    }
    
    
  • 相关阅读:
    K
    A
    2017 Multi-University Training Contest
    第一章 概述
    校赛F 比比谁更快(线段树)
    POJ 3683 Priest John's Busiest Day
    POJ 2186 Popular Cows
    第十五周讨论
    线段树模板(单点更新,区间更新,RMQ)
    2-SAT问题(白书)
  • 原文地址:https://www.cnblogs.com/Code-Geass/p/9931598.html
Copyright © 2011-2022 走看看