Luogu P1726 上白泽慧音
这显然是一道求强连通分量(SCC)的题目。
只要你正常,都知道应该写Tarjan。
然后(假装会写Tarjan),其实我当然不会。但是求SCC还有另一个算法。复杂度和Tarjan一样,只不过常数大了点而且不为人所知而已。
蓝书和挑战程序竞赛上都有这个算法,好像叫Kosaraju。是不是很拽的感觉。
具体的算法可以参照我的博客另一篇文章。重点是这道题就是SCC模板题(不敢相信竟然10分钟一次A了)
CODE
#include<cstdio> #include<vector> #include<cstring> using namespace std; const int N=5005; vector <int> a[N],b[N],s; int f[N],i,n,m,x,y,z,ans,num,c[N],tot,t[N]; inline void read(int &x) { x=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); } inline void dfs(int k) { f[k]=0; for (int i=0;i<a[k].size();++i) if (f[a[k][i]]) dfs(a[k][i]); s.push_back(k); } inline void rdfs(int k) { f[k]=0; c[k]=tot; t[tot]++; for (int i=0;i<b[k].size();++i) if (f[b[k][i]]) rdfs(b[k][i]); } int main() { read(n); read(m); for (i=1;i<=m;++i) { read(x); read(y); read(z); if (z==1) { a[x].push_back(y); b[y].push_back(x); } else { a[x].push_back(y); a[y].push_back(x); b[x].push_back(y); b[y].push_back(x); } } memset(f,true,sizeof(f)); for (i=1;i<=n;++i) if (f[i]) dfs(i); memset(f,true,sizeof(f)); for (i=s.size()-1;i;--i) if (f[s[i]]) ++tot,rdfs(s[i]); for (i=1;i<=tot;++i) if (t[i]>ans) ans=t[i],num=i; printf("%d\n",ans); for (i=1;i<=n;++i) if (c[i]==num) printf("%d ",i); return 0; }
辣鸡老年选手AFO在即