求強連通塊_Tarjan算法_C++


  好久沒有寫算法了,就放一個 Tarjan 上來湊湊數哈

  強連通塊由若干個點組成,任意點與點之間可以之間或間接到達,顯然可以看作一個環

  下面是偽代碼

     

  強記:dfn為時間不變,low取最小,下一個dfn有值就跟dfn取min,沒有就進去后跟low取,兩個相等時彈棧

  證明的話就貼一個

    

  會不會證無所謂了,可以自己腦補一下,況且代碼很好寫

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<stack>
 8 #define N 100000
 9 using namespace std;
10 
11 stack<int> p;
12 int next[N],first[N],v[N],t,dfn[N],low[N];
13 bool f[N];
14 void dfs(int x)
15 {
16     p.push(x);
17     dfn[x]=low[x]=++t;
18     int i;
19     for (i=first[x];i;i=next[i])
20         if (f[v[i]]) continue;
21         if (dfn[v[i]]) low[x]=min(low[x],dfn[v[i]]);
22         else
23             {
24                 dfs(v[i]);
25                 low[x]=min(low[x],low[v[i]]);
26             }
27     if (low[x]==dfn[x])
28         {
29             while (p.top()!=x)
30                 {
31                     f[p.top()]=1;
32                     printf("%d ",p.top());
33                     p.pop();
34                 }
35             f[p.top()]=1;
36             p.pop();
37             printf("%d\n",x);
38         }
39 }
40 int main()
41 {
42     freopen("tarjan.in","r",stdin);
43     freopen("tarjan.out","w",stdout);
44     int i,x,n,m;
45     scanf("%d%d",&n,&m);
46     for (i=1;i<=n;i++) f[i]=0;
47     for (i=1;i<=m;i++)
48         {
49             scanf("%d%d",&x,&v[i]);
50             next[i]=first[x];
51             first[x]=i;
52         }
53     for (i=1;i<=n;i++)
54         if (dfn[i]==0)
55             {
56                 t=0;
57                 dfs(i);
58             }
59     return 0;
60 }

 

 

 

版權所有,轉載請聯系作者,違者必究

QQ:740929894


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM