[targin]强联通分量+缩点

在一个有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强联通。

如果所有顶点都强联通,称G是一个强联通图。

非强联通图有向图的极大强联通子图,称为强联通分量。

深度优先搜索。

DFN(i):节点i被搜索到的次序编号。

LOW(i):i或i的子树能够追溯到的最早的节点的次序号。

LOW I = min ( dfn i  , low j , dfn j)

当DFN i = LOW i 以 i 为根的的子树上所有节点是一个强联通分量。

时间复杂度:O(N+M)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include <bits/stdc++.h>
 6 using namespace std;
 7 typedef long long ll;
 8 const ll mod=998244353;
 9 const int N=1e5+100;
10 const int maxn=1e6;
11 const int MAXL=sqrt(1e14)+1;
12 inline int read() {
13     char c = getchar(); int x = 0, f = 1;
14     while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
15     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
16     return x * f;
17 }
18 int n,m;
19 int Link[N],len=0,dfn[N],low[N],bok[N];
20 int belong[N],id,bcnt;
21 stack<int>s;
22 struct node
23 {
24     int y,next;
25 }e[2*N];
26 void insert(int xx,int yy)
27 {
28     e[++len].next=Link[xx];
29     Link[xx]=len;
30     e[len].y=yy;
31 }
32 void targin(int x)
33 {
34     dfn[x]=low[x]=++id;
35     s.push(x);
36     bok[x]=1;
37     for(int i=Link[x];i;i=e[i].next)
38     {
39         int v=e[i].y;
40         if(!dfn[v])
41         {
42             targin(v);
43             low[x]=min(low[x],low[v]);
44         }
45         else if(bok[v])
46         {
47             low[x]=min(low[x],dfn[v]);
48         }
49     }
50     if(dfn[x]==low[x])
51     {
52         bcnt++;
53         while(true)
54         {
55             int v=s.top();
56             s.pop();
57             bok[v]=0;
58             belong[v]=bcnt;
59             if(x==v)    break;
60         }
61     }
62 
63 }
64 int solve()
65 {
66     n=read();   m=read();
67     int xx,yy;
68     for(int i=1;i<=m;i++)
69     {
70         xx=read();  yy=read();
71         insert(xx,yy);
72     }
73     for(int i=1;i<=n;i++)
74         if(!dfn[i])
75             targin(i);
76 
77 
78 }
79 
80 
81 int main()
82 {
83     int T=1;
84     scanf("%d",&T);
85     //T=1;
86     //cout<<tot<<endl;
87     int tt=0;
88     while(T--)
89 
90     {
91         //if(n==0)    break;
92         //printf("Case %d: ",++tt);
93         solve();
94     }
95 
96     return 0;
97 
98 }
View Code

 

缩点:

for(int i=1;i<=n;i++)
    {
        for(int j=Link[i];j;j=e[i].next)
        {
            int v=e[j].y;
            if(belong[i]!=belong[v])
                insert(belong[i],belong[v]);
        }
    }

 

posted @ 2021-03-06 14:25  kaike  阅读(94)  评论(0编辑  收藏  举报