# Dominator Tree & Lengauer-Tarjan Algorithm

### 什么是支配树

1.如果i是j的必经点，而j又是k的必经点，则i也是k的必经点。

2.如果i和j都是k的必经点，则i和j之间必然存在必经点关系，不可能互相都不是必经点。

### 简单的上手题

CodeChef Counting on a directed graph GRAPHCNT

  1 #include <bits/stdc++.h>
2
3 using namespace std;
4
5 typedef long long lnt;
6
7 const int mxn = 100005;
8
9 int n, m;
10
11 int tim;
12 int dfn[mxn];
13 int idx[mxn];
14 int fat[mxn];
15 int idm[mxn];
16 int sdm[mxn];
17 int anc[mxn];
18 int tag[mxn];
19 lnt siz[mxn];
20 lnt son[mxn];
21
22 vector<int> G[mxn];
23 vector<int> R[mxn];
24 vector<int> S[mxn];
25 vector<int> T[mxn];
26
27 void dfsG(int u)
28 {
29     idx[dfn[u] = ++tim] = u;
30
31     for (auto v : G[u])if (!dfn[v])
32         fat[v] = u, dfsG(v);
33 }
34
35 void dfsT(int u)
36 {
37     siz[u] = 1;
38
39     for (auto v : T[u])
40         dfsT(v), siz[u] += siz[v];
41 }
42
43 int find(int u)
44 {
45     if (u == anc[u])
46         return u;
47
48     int r = find(anc[u]);
49
50     if (dfn[sdm[tag[anc[u]]]] < dfn[sdm[tag[u]]])
51         tag[u] = tag[anc[u]];
52
53     return anc[u] = r;
54 }
55
56 signed main(void)
57 {
58     cin >> n >> m;
59
60     for (int i = 1, u, v; i <= m; ++i)
61     {
62         cin >> u >> v;
63         G[u].push_back(v);
64         R[v].push_back(u);
65     }
66
67     for (int i = 1; i <= n; ++i)
68         sdm[i] = tag[i] = anc[i] = i;
69
70     dfsG(1);
71
72     for (int i = tim; i > 1; --i)
73     {
74         int u = idx[i];
75
76         for (auto v : R[u])if (dfn[v])
77         {
78             find(v);
79             if (dfn[sdm[tag[v]]] < dfn[sdm[u]])
80                 sdm[u] = sdm[tag[v]];
81         }
82
83         anc[u] = fat[u];
84
85         S[sdm[u]].push_back(u);
86
87         int t = idx[i - 1];
88
89         for (auto v : S[t])
90         {
91             find(v);
92             if (sdm[tag[v]] == t)
93                 idm[v] = t;
94             else
95                 idm[v] = tag[v];
96         }
97
98         S[t].clear();
99     }
100
101     for (int i = 2; i <= tim; ++i)
102     {
103         int u = idx[i];
104         if (idm[u] != sdm[u])
105             idm[u] = idm[idm[u]];
106     }
107
108     for (int i = 2; i <= tim; ++i)
109         T[idm[i]].push_back(i);
110
111     dfsT(1);
112
113     lnt ans = tim * (tim - 1);
114
115     for (int i = tim, u; i >= 2; --i)
116     {
117         ++son[u = idx[i]];
118         if (idm[u] != 1)
119             son[idm[u]] += son[u];
120         else
121             ans -= son[u] * (son[u] - 1);
122     }
123
124     ans >>= 1;
125
126     cout << ans << endl;
127 } 
View Code

HDU 4694 Important Sisters

  1 #include <cstdio>
2 #include <cstring>
3
4 #define mxn 50005
5 #define mxm 200005
6 #define lnt long long
7
8 int n, m;
9
10 struct Lin {
11     int tt;
12     int hd[mxn];
13     int nt[mxm];
14     int to[mxm];
15
16     void init(void) {
17         memset(hd, 0, sizeof hd), tt = 0;
18     }
19
20     void adde(int u, int v) {
21         nt[++tt] = hd[u], to[tt] = v, hd[u] = tt;
22     }
23 }G, R, T, S;
24
25 int tim;
26 int idx[mxn];
27 int dfn[mxn];
28 int fat[mxn];
29 int anc[mxn];
30 int tag[mxn];
31 int sdm[mxn];
32 int idm[mxn];
33 lnt ans[mxn];
34
35 void dfsG(int u) {
36     idx[dfn[u] = ++tim] = u;
37
38     for (int i = G.hd[u], v; i; i = G.nt[i])
39         if (!dfn[v = G.to[i]])dfsG(v), fat[v] = u;
40 }
41
42 void dfsT(int u) {
43     ans[u] += u;
44
45     for (int i = T.hd[u], v; i; i = T.nt[i])
46         ans[v = T.to[i]] += ans[u], dfsT(v);
47 }
48
49 int find(int u) {
50     if (anc[u] == u)return u;
51
52     int r = find(anc[u]);
53
54     if (dfn[sdm[tag[anc[u]]]] < dfn[sdm[tag[u]]])
55         tag[u] = tag[anc[u]];
56
57     return anc[u] = r;
58 }
59
60 signed main(void)
61 {
62     while (scanf("%d%d", &n, &m) != EOF) {
63         memset(ans, 0, sizeof ans);
64         memset(dfn, 0, sizeof dfn), tim = 0;
65
66         G.init(); R.init(); T.init(); S.init();
67
68         for (int i = 1, u, v; i <= m; ++i)
70
71         for (int i = 1; i <= n; ++i)
72             sdm[i] = tag[i] = anc[i] = i;
73
74         dfsG(n);
75
76         for (int i = tim; i > 1; --i) {
77             int u = idx[i], v;
78
79             for (int j = R.hd[u]; j; j = R.nt[j])
80                 if (dfn[v = R.to[j]]) {
81                     find(v);
82                     if (dfn[sdm[tag[v]]] < dfn[sdm[u]])
83                         sdm[u] = sdm[tag[v]];
84                 }
85
86             anc[u] = fat[u]; S.adde(sdm[u], u); u = idx[i - 1];
87
88             for (int j = S.hd[u]; j; j = S.nt[j]) {
89                 find(v = S.to[j]);
90                 if (sdm[tag[v]] == u)
91                     idm[v] = u;
92                 else
93                     idm[v] = tag[v];
94             }
95         }
96
97         for (int i = 2; i <= tim; ++i) {
98             int u = idx[i];
99             if (idm[u] != sdm[u])
100                 idm[u] = idm[idm[u]];
102         }
103
104         dfsT(n);
105
106         for (int i = 1; i < n; ++i)
107             printf("%lld ", ans[i]);
108
109         printf("%lld\n", ans[n]);
110     }
111 }
View Code

SPOJ BIA - Bytelandian Information Agency

  1 #include <bits/stdc++.h>
2
3 using namespace std;
4
5 const int mxn = 5005;
6 const int mxm = 200005;
7
8 int n, m;
9
10 vector<int> G[mxn];
11 vector<int> R[mxn];
12 vector<int> S[mxn];
13
14 inline void init(vector<int> v[mxn])
15 {
16     for (int i = 0; i < mxn; ++i)
17         v[i].clear();
18 }
19
20 int tim;
21 int dfn[mxn];
22 int idx[mxn];
23 int fat[mxn];
24 int idm[mxn];
25 int sdm[mxn];
26 int anc[mxn];
27 int cnt[mxn];
28 int tag[mxn];
29
30 void dfsG(int u)
31 {
32     idx[dfn[u] = ++tim] = u;
33
34     for (auto v : G[u])if (!dfn[v])
35         fat[v] = u, dfsG(v);
36 }
37
38 int find(int u)
39 {
40     if (anc[u] == u)
41         return u;
42
43     int r = find(anc[u]);
44
45     if (dfn[sdm[tag[anc[u]]]] < dfn[sdm[tag[u]]])
46         tag[u] = tag[anc[u]];
47
48     return anc[u] = r;
49 }
50
51 signed main(void)
52 {
53     while (cin >> n >> m)
54     {
55         init(G);
56         init(R);
57         init(S);
58
59         tim = 0;
60
61         memset(cnt, 0, sizeof cnt);
62         memset(dfn, 0, sizeof dfn);
63
64         for (int i = 1, u, v; i <= m; ++i)
65         {
66             cin >> u >> v;
67             G[u].push_back(v);
68             R[v].push_back(u);
69         }
70
71         for (int i = 1; i <= n; ++i)
72             sdm[i] = tag[i] = anc[i] = i;
73
74         dfsG(1);
75
76         for (int i = tim; i > 1; --i)
77         {
78             int u = idx[i];
79
80             for (auto v : R[u])if (dfn[v])
81             {
82                 find(v);
83                 if (dfn[sdm[tag[v]]] < dfn[sdm[u]])
84                     sdm[u] = sdm[tag[v]];
85             }
86
87             anc[u] = fat[u];
88
89             S[sdm[u]].push_back(u);
90
91             u = idx[i - 1];
92
93             for (auto v : S[u])
94             {
95                 find(v);
96
97                 if (sdm[tag[v]] == u)
98                     idm[v] = u;
99                 else
100                     idm[v] = tag[v];
101             }
102
103             S[u].clear();
104         }
105
106         for (int i = 2; i <= tim; ++i)
107         {
108             int u = idx[i];
109             if (idm[u] != sdm[u])
110                 idm[u] = idm[idm[u]];
111         }
112
113         for (int i = 2; i <= tim; ++i)
114             ++cnt[idm[i]];
115
116         int ans = 0;
117
118         for (int i = 1; i <= tim; ++i)
119             if (cnt[i])++ans;
120
121         cout << ans << endl;
122
123         for (int i = 1; i <= tim; ++i)
124             if (cnt[i])cout << i << " ";
125
126         cout << endl;
127     }
128 }
View Code