洛谷P1726上白泽慧音

裸的tarjan缩点,不要管双向边,你就把他看成两条单向边就行了

代码

//By AcerMo
#include<cmath>
#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=100500;
stack<int>s;
int n,cnt,m,ind,ti,ms,af;
int to[M],nxt[M],head[M];
int dfn[M],low[M],vis[M],fa[M],siz[M];
inline int read()
{
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}
inline void add(int x,int y,int f)
{
	to[++cnt]=y;nxt[cnt]=head[x];head[x]=cnt;
	if (f==2) 
	to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;	
	return ;
}
inline void tarjan(int x)
{
	low[x]=dfn[x]=++ind;vis[x]=1;s.push(x);
	for (int i=head[x];i;i=nxt[i])
	{
		if (!dfn[to[i]])
		{
			tarjan(to[i]);low[x]=min(low[x],low[to[i]]);
		}
		else if (vis[to[i]])
			low[x]=min(low[x],dfn[to[i]]);
	}
	if (low[x]==dfn[x])
	{
		int u=-1;ti++;
		while (u!=x)
		{
			u=s.top();s.pop();
			vis[u]=0;fa[u]=ti;
			siz[ti]++;
			if (siz[ti]>ms) af=ti,ms=siz[ti];
		}
	}
	return ;
}
signed main()
{
	n=read();m=read();int x,y,z;
	for (int i=1;i<=m;i++)
		x=read(),y=read(),z=read(),add(x,y,z);
	for (int i=1;i<=n;i++)
	if (!dfn[i]) tarjan(i);
	printf("%d\n",ms);
	for (int i=1;i<=n;i++)
	if (fa[i]==af) printf("%d ",i);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ACerAndAKer/article/details/81697706