【UOJ#67】新年的毒瘤(Tarjan)

【UOJ#67】新年的毒瘤(Tarjan)

题面

UOJ

题解

一棵\(n\)个节点的树显然有\(n-1\)条边,在本题中意味着删去一个点之后还剩下\(n-2\)条边。那么找到所有度数为\(m-(n-2)\)的点就好了。但是因为是一棵树,所以联通,所以割点不是答案。

#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
#define MAX 100100
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1,dg[MAX];
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;dg[u]++;}
int n,m,dfn[MAX],low[MAX],tim,S[MAX],top,rt,son;
bool cut[MAX];
void Tarjan(int u,int ff)
{
	dfn[u]=low[u]=++tim;
	for(int i=h[u];i;i=e[i].next)
	{
		int v=e[i].v;if(v==ff)continue;
		if(!dfn[v])
		{
			Tarjan(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u])
			{
				if(u^rt)cut[u]=true;
				else ++son;
			}
		}
		else low[u]=min(low[u],dfn[v]);
	}
	if(u==rt&&son>1)cut[u]=true;
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=m;++i)
	{
		int u=read(),v=read();
		Add(u,v);Add(v,u);
	}
	for(int i=1;i<=n;++i)if(!dfn[i])Tarjan(rt=i,son=0);
	for(int i=1;i<=n;++i)if(!cut[i]&&(m-dg[i]==n-2))S[++top]=i;
	printf("%d\n",top);
	for(int i=1;i<=top;++i)printf("%d ",S[i]);
	puts("");return 0;
}
posted @ 2018-09-25 11:46  小蒟蒻yyb  阅读(382)  评论(0编辑  收藏  举报