tarjan 强联通分量和割点
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<ctime> 5 #include<iostream> 6 #include<algorithm> 7 #include<queue> 8 #include<stack> 9 #include<set> 10 #define esp (1e-6) 11 #define inf (0x3f3f3f3f) 12 #define l(a) ((a)<<1) 13 #define r(a) ((a)<<1|1) 14 #define b(a) (1<<(a)) 15 #define rep(i,a,b) for(int i=a;i<=(b);i++) 16 #define clr(a) memset(a,0,sizeof(a)) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 using namespace std; 20 int readint(){ 21 int t=0,f=1;char c=getchar(); 22 while(!isdigit(c)){ 23 if(c=='-') f=-1; 24 c=getchar(); 25 } 26 while(isdigit(c)){ 27 t=(t<<3)+(t<<1)+c-'0'; 28 c=getchar(); 29 } 30 return t*f; 31 } 32 const int maxn=100009,maxm=200009; 33 struct edge{ 34 int v; 35 edge*next; 36 }e[maxm],*pt=e,*fir[maxn]; 37 int n,m,ans,dfstime,scccnt,size[maxn],pre[maxn],low[maxn],scc[maxn]; 38 bool p[maxn]; 39 void add(int u,int v){ 40 pt->v=v;pt->next=fir[u]; 41 fir[u]=pt++; 42 } 43 void addedge(int u,int v){ 44 add(u,v);add(v,u); 45 } 46 stack<int>S; 47 void dfs(int x,int f){ 48 int son=0; 49 pre[x]=low[x]=++dfstime;S.push(x); 50 for(edge*e=fir[x];e;e=e->next) if(e->v!=f){ 51 if(!pre[e->v]){ 52 son++;dfs(e->v,x); 53 low[x]=min(low[x],low[e->v]); 54 if(f!=-1&&low[e->v]>=pre[x]) p[x]=1; 55 }else if(!scc[e->v]) low[x]=min(low[x],pre[e->v]); 56 } 57 if(f==-1&&son>1) if(!p[x]) p[x]=1; 58 if(pre[x]==low[x]){ 59 int t=-1;++scccnt; 60 while(t!=x){ 61 t=S.top();S.pop(); 62 scc[t]=scccnt;size[scccnt]++; 63 } 64 } 65 } 66 void tarjan(){ 67 rep(i,1,n) if(!scc[i]) dfs(i,-1); 68 rep(i,1,n) if(p[i]) ans++; 69 cout<<ans<<endl; 70 rep(i,1,n) if(p[i]){ 71 ans--;printf("%d",i); 72 putchar(ans?' ':'\n'); 73 } 74 } 75 int main(){ 76 //freopen("#input.txt","r",stdin); 77 //freopen("#output.txt","w",stdout); 78 n=readint();m=readint(); 79 rep(i,1,m){ 80 int U=readint(),V=readint(); 81 addedge(U,V); 82 } 83 tarjan(); 84 //fclose(stdin); 85 //fclose(stdout); 86 return 0; 87 }