机房真实NOIP模拟赛--pure和dirty系列题

这道题说白了就是一道点双联通分量的板子题

权当练习

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define RG register
using namespace std;
int nxt[200005],to[200005],head[100005],shu1,shu2,n,m,tot;
int dfn[100005],low[100005],stk[100005],instk[100005];
int ans[100005],pd[100005];
int id[200005],dfs_num,top,cnt,inv[100005];
vector <int> point[100005];
inline int minn(int x,int y)
{
	if(x<y) return x;
	return y;
}
inline int read()
{
    int ans=0,t=1;
    char x=getchar();
    while(x<'0'||x>'9')
    {
        if(x=='-') t=-1;
        x=getchar();
    }
    while(x>='0'&&x<='9')
    {
        ans=ans*10+x-'0';
        x=getchar();
    }
    return ans*t;
}
inline void add(int x,int y,int z)
{
	to[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
	id[tot]=z;
}
void tarjan(int x,int fa)
{
	dfn[x]=low[x]=++dfs_num;
	for(RG int i=head[x];i;i=nxt[i])
	{
		int y=to[i];
		if(y==fa) continue;
		if(!dfn[y])
		{
			stk[++top]=y;
			tarjan(y,x);
			low[x]=minn(low[x],low[y]);
			if(low[y]>=dfn[x])
			{
				cnt++;
				while(233)
				{
					int now=stk[top--];
					point[cnt].push_back(now);
					if(now==y) break;
				}
				point[cnt].push_back(x);
			}
		}
		else  
		{
			low[x]=minn(dfn[y],low[x]);
		}
	}
}
int main()
{
	freopen("find.in","r",stdin);
	freopen("find.out","w",stdout);
	cin>>n>>m;
	for(RG int i=1;i<=m;i++)
	{
		shu1=read();
		shu2=read();
		add(shu1,shu2,i);
		add(shu2,shu1,i);
	}
	for(RG int i=1;i<=n;i++)
	if(!dfn[i])
	  tarjan(i,i);
	for(RG int l=1;l<=cnt;l++)
	{
		for(RG int j=0;j<point[l].size();j++)
		inv[point[l][j]]=1;
		for(RG int k=0;k<point[l].size();k++)
		{
			RG int i=point[l][k];
			for(RG int j=head[i];j;j=nxt[j])
			{
				RG int y=to[j];
				if(inv[y])
				{
					ans[l]++;
				}
			}
		}
		for(RG int j=0;j<point[l].size();j++)
		inv[point[l][j]]=0;
	}
	for(RG int l=1;l<=cnt;l++)
	{
		for(RG int j=0;j<point[l].size();j++)
		inv[point[l][j]]=1;
		for(RG int k=0;k<point[l].size();k++)
		{
			RG int i=point[l][k];
			for(RG int j=head[i];j;j=nxt[j])
			{
				RG int y=to[j];
				if(inv[y])
				{
					if(ans[l]==(((int)point[l].size())<<1))
					pd[id[j]]=1;
				}
			}
		}
		for(RG int j=0;j<point[l].size();j++)
		inv[point[l][j]]=0;
	}
	RG int all=0;
	for(RG int i=1;i<=m;i++)
	   if(pd[i])
	       all++;
	printf("%d\n",all);
	for(RG int i=1;i<=m;i++)
	if(pd[i])
	printf("%d ",i);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ENESAMA/article/details/82813354