强连通分量Kosaraju
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> using namespace std; const int maxn=1e5+5; const int maxm=2e5+5; inline int read(){ int a = 0; bool b = 1; char x = getchar(); while(x<'0'||'9'<x){ if(x=='-')b=0; x=getchar(); } while('0'<=x && x<='9'){ a=(a<<3)+(a<<1)+x-'0'; x=getchar(); } return b ? a : -a ; } int n,m; int first[maxn][2],next[maxm][2],to[maxm][2],end[maxn]; int edge_count[2]; inline void add(int x,int y,bool b){ edge_count[b]++; to[ edge_count[b] ][b]=y; next[ edge_count[b] ][b]=first[x][b]; first[x][b]=edge_count[b]; } int vis[maxn]; int Time=0;//时间戳 void dfs_one(int x){ vis[x]=1; for(int i=first[x][0];i;i=next[i][0]){ if(!vis[ to[i][0] ])dfs_one(to[i][0]); } end[++Time]=x; } int temp=0,cnt[maxn]; void dfs_two(int x){ vis[x]=temp; cnt[temp]++; for(int i=first[x][1];i;i=next[i][1]){ if(vis[ to[i][1] ])continue; dfs_two(to[i][1]); } } //0->正向 ,1->反向 int main() { n=read();m=read(); for(int i=1,a,b;i<=m;i++){ a=read();b=read(); add(a,b,0);add(b,a,1); } for(int i=1;i<=n;i++){if(!vis[i])dfs_one(i);} memset(vis,0,sizeof(vis)); for(int i=n;i;i--){ if(vis[ end[i] ])continue; temp++; dfs_two(end[i]); } for(int i=1;i<=n;i++){ if(cnt[ vis[i] ]>1)printf("T\n"); else printf("F\n"); } return 0; }