nssl 1504.决战

D e s c r i p t i o n Description Description

给定一张 n n n个点, m m m条边的无向连通图,问有多少个点满足删除这个点后,剩下的图无环且联通

数据范围: n ≤ 1 0 5 , m ≤ 1 0 5 n\leq 10^5,m\leq 10^5 n105,m105


S o l u t i o n Solution Solution

这个点不能是割点
割完之后的图必定是一棵树(边数+1=点数)

记录度数(连接的边的个数),用 t a r j a n tarjan tarjan求割点即可

时间复杂度: O ( n + m ) O(n+m) O(n+m)


C o d e Code Code

#include
#include
#include
#include
#include
#define LL long long
#define N 100010
using namespace std;int n,m,x,y,rd[N],l[N],tot,ans,dfn[N],low[N],cnt,rt;
bool ds1[N],flg,hs[N],cut[N];
struct node{int next,to;}e[N*2];
inline void add(int u,int v){e[++tot]=(node){l[u],v};l[u]=tot;return;}
inline LL read()
{
	char c;LL d=1,f=0;
	while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
inline void tarjan(int x) 
{
	dfn[x]=low[x]=++cnt;
	int flag=0;
	for(register int i=l[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(dfn[y]==0)
		{
			tarjan(y);
			low[x]=min(low[x],low[y]);
			if(low[y]>=dfn[x]) 
			{
				flag++;
				if(flag>1||x!=rt) cut[x]=true;
			}
		}else low[x]=min(low[x],dfn[y]);
	}
	return;
}
signed main()
{
	n=read();m=read();
	for(register int i=1;i<=m;i++)
	{
		x=read();y=read();
		rd[x]++;rd[y]++;
		add(x,y);add(y,x);
	}
	for(register int i=1;i<=n;i++) if(dfn[i]==0) tarjan(rt=i);
	for(register int i=1;i<=n;i++) if(cut[i]==0&&n-1==m-rd[i]+1) ans++;
	printf("%d\n",ans);
	for(register int i=1;i<=n;i++) if(cut[i]==0&&n-1==m-rd[i]+1) printf("%d ",i);
}

你可能感兴趣的:(tarjan,GT)