Tarjan 割点 割边 缩点 SCC🤪

// 不错的博客眼👁 (本文中的图片来源地)

 

 

 

 

 

 // 割点 UVA 315

 1 /*
 2  * @Promlem: 
 3  * @Time Limit: ms
 4  * @Memory Limit: k
 5  * @Author: pupil-XJ
 6  * @Date: 2019-10-30 23:24:12
 7  * @LastEditTime: 2019-10-31 01:45:55
 8  */
 9 #include<cstdio>
10 #include<cstring>
11 #include<iostream>
12 #include<algorithm>
13 #include<set>
14 #define rep(i, n) for(int i=0;i!=n;++i)
15 #define rep1(i, n) for(int i=1;i<=n;++i)
16 using namespace std;
17 // -----------------------------------------------------
18 const int MAXN = 100+5;
19 const int MAXM = MAXN*MAXN;
20 
21 int num;
22 int head[MAXN];
23 struct node {
24     int v, next;
25 } edge[MAXM];
26 
27 inline void add(int x, int y) {
28     edge[num].v = y;
29     edge[num].next = head[x];
30     head[x] = num++;
31 }
32 
33 int n;
34 int cnt;
35 int dfn[MAXN], low[MAXN];
36 set<int> disct;
37 
38 void Tarjan(int cur, int root) {
39     dfn[cur] = low[cur] = ++cnt;
40     int flag = 0;
41     for(int i = head[cur]; i != -1; i = edge[i].next) {
42         int v = edge[i].v;
43         if(!dfn[v]) {
44             Tarjan(v, root);
45             low[cur] = min(low[cur], low[v]);
46             if(low[v] >= dfn[cur]) {
47                 ++flag;
48                 if(cur != root || flag > 1) disct.insert(cur);    
49             }
50         }
51         else low[cur] = min(low[cur], dfn[v]);
52     }
53 }
54 
55 void solve() {
56     cnt = 0;
57     disct.clear();
58     rep1(i, n) dfn[i] = low[i] = 0;
59     rep1(i, n) if(!dfn[i]) Tarjan(i, i);
60     cout << disct.size() << "\n";
61 }
62 
63 int main() {
64     while(cin >> n && n) {
65         num = 0;
66         rep1(i, n) head[i] = -1;
67         int u, v;
68         while(cin >> u && u) {
69             while(getchar() != '\n') {
70                 cin >> v;
71                 add(u, v); add(v, u);
72             }
73         }
74         solve();
75     }
76     return 0;
77 }
View Code

// 割边 UVA 796

 1 /*
 2  * @Promlem: 
 3  * @Time Limit: ms
 4  * @Memory Limit: k
 5  * @Author: pupil-XJ
 6  * @Date: 2019-10-31 01:44:42
 7  * @LastEditTime: 2019-10-31 11:34:30
 8  */
 9 #include<cstdio>
10 #include<algorithm>
11 #include<vector>
12 #define rep(i, n) for(int i=0;i!=n;++i)
13 #define rep1(i, n) for(int i=1;i<=n;++i)
14 using namespace std;
15 const int MAXN = 1000+5;
16 const int MAXM = MAXN*MAXN;
17 typedef pair<int,int> Pair;
18 
19 int num;
20 int head[MAXN];
21 struct node {
22     int v, next;
23 } edge[MAXM];
24 
25 inline void add(int x, int y) {
26     edge[num].v = y;
27     edge[num].next = head[x];
28     head[x] = num++;
29 }
30 
31 int cnt;
32 int dfn[MAXN], low[MAXN];
33 bool bridge[MAXM];
34 void Tarjan(int cur, int edge_num) {
35     dfn[cur] = low[cur] = ++cnt;
36     for(int i = head[cur]; i != -1; i = edge[i].next) {
37         int v = edge[i].v;
38         if(!dfn[v]) {
39             Tarjan(v, i);
40             low[cur] = min(low[cur], low[v]);
41             if(low[v] > dfn[cur]) bridge[i] = bridge[i^1] = true;
42         }
43         else if(i != (edge_num^1)) low[cur] = min(low[cur], dfn[v]);
44     }
45 }
46 
47 int n;
48 vector<Pair> ans;
49 
50 void solve() {
51     cnt = 0;
52     ans.clear();
53     rep(i, num) bridge[i] = false;
54     rep(i, n) dfn[i] = 0;
55     rep(i, n) if(!dfn[i]) Tarjan(i, 0);
56     for(int i = 0; i != num; i += 2) {
57         if(bridge[i]) {
58             if(edge[i].v > edge[i^1].v) ans.push_back(make_pair(edge[i^1].v, edge[i].v));
59             else ans.push_back(make_pair(edge[i].v, edge[i^1].v));
60         }
61     }
62     sort(ans.begin(), ans.end());
63     printf("%d critical links\n",ans.size());
64     rep(i, ans.size()) {
65         printf("%d - %d\n",ans[i].first,ans[i].second);
66     }
67     printf("\n");
68 }
69 
70 int main() {
71     while(scanf("%d", &n) == 1) {
72         num = 0;
73         rep(i, n) head[i] = -1;
74         int u, v, nm;
75         rep(i, n) {
76             scanf("%d (%d)", &u, &nm);
77             rep(j, nm) {
78                 scanf("%d", &v);
79                 if(u < v) add(u, v), add(v, u);
80             }
81         }
82         solve();
83     }
84     return 0;
85 }
View Code

// 缩点 poj 2186

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 const int MAXN = 10000+5;
 7 const int MAXM = 50000+5;
 8 
 9 struct node {
10     int v, next;
11 } edge[MAXM];
12 int num;
13 
14 int head[MAXN];
15 
16 inline void add_edge(int x, int y) {
17     edge[num].v = y;
18     edge[num].next = head[x];
19     head[x] = num++;
20 }
21 
22 int cnt, t, scc_cnt;
23 int dfn[MAXN], low[MAXN], vis[MAXN], sccno[MAXN], stack[MAXN];
24 int scc_num[MAXN], out[MAXN];
25 
26 inline void Tarjan(int cur) {
27     dfn[cur] = low[cur] = ++cnt;
28     stack[t++] = cur;
29     for(int i = head[cur]; i != -1; i = edge[i].next) {
30         if(!dfn[edge[i].v]) {
31             Tarjan(edge[i].v);
32             low[cur] = min(low[cur], low[edge[i].v]);
33         }
34         else if(vis[edge[i].v]) {
35             low[cur] = min(low[cur], dfn[edge[i].v]);
36         }
37     }
38     if(dfn[cur] == low[cur]) {
39         ++scc_cnt;
40         int v;
41         do {
42             v = stack[--t];
43             sccno[v] = scc_cnt;
44             ++scc_num[scc_cnt];
45             vis[v] = 0;
46         } while(v != cur);
47     }
48 }
49 
50 int main() {
51     int n, m;
52     scanf("%d%d", &n, &m);
53     memset(head, -1, sizeof(head));
54     int x, y;
55     for(int i = 0; i != m; ++i) {
56         scanf("%d%d", &x, &y);
57         add_edge(x, y);
58     }
59     for(int i = 1; i <= n; ++i) {
60         if(!dfn[i]) Tarjan(i);
61     }
62     for(int i = 1; i <= n; ++i) {
63         for(int j = head[i]; j != -1; j = edge[j].next) {
64             int a = sccno[i], b = sccno[edge[j].v];
65             if(a != b) ++out[sccno[i]];
66         }
67     }
68     int ans = 0;
69     int flag;
70     for(int i = 1; i <= scc_cnt; ++i) {
71         if(!out[i]) {
72             ++ans;
73             flag = i;
74         }
75     }
76     if(ans == 1) printf("%d\n", scc_num[flag]);
77     else printf("0\n");
78     return 0;
79 }
View Code

// SCC

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<stack>
 4 using namespace std;
 5 
 6 const int MAXN = 1000+5;
 7 
 8 struct node {
 9     int v, next;
10 } edge[2*MAXN];
11 int num;
12 
13 int head[2*MAXN];
14 int dfn[MAXN], low[MAXN], sccno[MAXN], vis[MAXN];
15 stack<int> sk;
16 int cnt, scc_cnt;
17 
18 void add_edge(int x, int y) {
19     edge[num].v = y;
20     edge[num].next = head[x];
21     head[x] = num++;
22 }
23 
24 void tarjan(int cur) {
25     dfn[cur] = low[cur] = ++cnt;// dfn给结点设定次序 low初始化(u及其后代能追溯到的最早-最先被发现 祖先点v的dfn[v]值)
26     sk.push(cur);
27     for(int i = head[cur]; i != -1; i = edge[i].next) {
28         if(!dfn[edge[i].v]) {
29             tarjan(edge[i].v);
30             low[cur] = min(low[cur], low[edge[i].v]);
31         }
32         else if(vis[edge[i].v]) {
33             low[cur] = min(low[cur], dfn[edge[i].v]);
34         }
35     }
36     if(dfn[cur] == low[cur]) {
37         ++scc_cnt;
38         for(;;) {
39             int x = sk.top(); sk.pop();
40             sccno[x] = scc_cnt;
41             vis[x] = 0;
42             printf("%d ", x);
43             if(x == cur) break;
44         }
45         printf("\n");
46     }
47 }
48 
49 int main() {
50     memset(head, -1, sizeof(head));54     num = 0;
51     cnt = 0;
52     scc_cnt = 0;
53 
54     int n, m; // n个点 m条边
55     scanf("%d%d", &n, &m);
56     int s, e;
57     for(int i = 0; i != m; ++i) {
58         scanf("%d%d", &s, &e);
59         add_edge(s, e);
60     }
61     for(int i = 1; i <= n; ++i) {
62         if(!dfn[i]) tarjan(i);
63     }
64     return 0;
65 }
66 input:
67 8
68 3
69 2
70 4
71 4
72 5
73 6
74 1
75 6
76 output:
77 5
78 4 2 1
View Code

 

posted @ 2019-10-31 09:52  pupil337  阅读(176)  评论(0编辑  收藏  举报