# Tarjan

1.有向图求强连通分量并缩点。

  1 #include <cstdio>
2 #include <algorithm>
3 #include <queue>
4 const int N = 10010, M = 100010;
5
6 struct Edge {
7     int u, v, nex;
8 }edge[M]; int top;
9 int e[N], dfn[N], low[N], num;
10 int stk[N], t, val[N];
11 bool in_stk[N];
12
13 Edge scc_edge[M];
14 int scc_e[N], scc_top, scc_in[N], scc_cnt, scc_val[N];
15 int topo[N], fr[N];
16
17 inline void add(int x, int y) {
18     ++top;
19     edge[top].u = x;
20     edge[top].v = y;
21     edge[top].nex = e[x];
22     e[x] = top;
23     return;
24 }
25
26 inline void scc_add(int x, int y) {
27     scc_top++;
28     scc_edge[scc_top].v = y;
29     scc_edge[scc_top].nex = scc_e[x];
30     scc_e[x] = scc_top;
31     scc_in[y]++;
32     return;
33 }
34
35 void tarjan(int x) {
36     dfn[x] = low[x] = ++num;
37     stk[++t] = x;
38     in_stk[x] = 1;
39     for(int i = e[x]; i; i = edge[i].nex) {
40         int y = edge[i].v;
41         if(!dfn[y]) {
42             tarjan(y);
43             low[x] = std::min(low[x], low[y]);
44         }
45         else if(in_stk[y]) {
46             low[x] = std::min(low[x], dfn[y]);
47         }
48     }
49     if(dfn[x] == low[x]) {
50         scc_cnt++;
51         int y;
52         do {
53             y = stk[t--];
54             in_stk[y] = 0;
55             fr[y] = scc_cnt;
56             scc_val[scc_cnt] += val[y];
57         }while(y != x);
58     }
59     return;
60 }
61
62 inline void topo_sort() {
63     std::queue<int> Q;
64     int temp = 0;
65     for(int i = 1; i <= scc_cnt; i++) {
66         if(!scc_in[i]) {
67             Q.push(i); /// error : topo[++num] = i;
68         }
69     }
70     while(!Q.empty()) {
71         int x = Q.front();
72         Q.pop();
73         topo[++temp] = x;
74         for(int i = scc_e[x]; i; i = scc_edge[i].nex) {
75             int y = scc_edge[i].v;
76             scc_in[y]--;
77             if(!scc_in[y]) {
78                 Q.push(y);
79             }
80         }
81     }
82     return;
83 }
84
85 int main() {
86     int n, m;
87     scanf("%d%d", &n, &m);
88     for(int i = 1; i <= n; i++) {
89         scanf("%d", &val[i]);
90     }
91     for(int i = 1, x, y; i <= m; i++) {
92         scanf("%d%d", &x, &y);
93         if(x == y) {
94             continue; /// error : space
95         }
97     }
98     for(int i = 1; i <= n; i++) {
99         if(!dfn[i]) {
100             tarjan(i);
101         }
102     }
103
104     for(int i = 1; i <= top; i++) {
105         int x = edge[i].u;
106         int y = edge[i].v;
107         if(fr[x] != fr[y]) {
109         }
110     }
111     int ans = 0;
112     topo_sort();
113     for(int i = scc_cnt; i; i--) {
114         int x = topo[i];
115         int temp = 0;
116         for(int j = scc_e[x]; j; j = scc_edge[j].nex) {
117             int y = scc_edge[j].v;
118             temp = std::max(temp, scc_val[y]);
119         }
120         scc_val[x] += temp;
121         ans = std::max(ans, scc_val[x]);
122     }
123     printf("%d\n", ans);
124     return 0;
125 }
scc缩点

tarjan scc已经打得比较熟了。

 1 #include <cstdio>
2 #include <algorithm>
3 #include <vector>
4
5 const int N = 5010, M = 50010;
6
7 struct Edge {
8     int v, nex;
9 }edge[M << 1]; int top;
10 int e[N], low[N], dfn[N], num;
11 int stk[N], t, scc_cnt;
12 bool in_stk[N];
13 std::vector<int> scc[N];
14
15 void tarjan(int x) {
16     dfn[x] = low[x] = ++num;
17     stk[++t] = x;
18     in_stk[x] = 1;
19     for(int i = e[x]; i; i = edge[i].nex) {
20         int y = edge[i].v;
21         if(!dfn[y]) {
22             tarjan(y);
23             low[x] = std::min(low[x], low[y]);
24         }
25         else if(in_stk[y]) {
26             low[x] = std::min(low[x], dfn[y]);
27         }
28     }
29     if(low[x] == dfn[x]) {
30         scc_cnt++;
31         int y;
32         do {
33             y = stk[t--];
34             in_stk[y] = 0;
35             scc[scc_cnt].push_back(y);
36         }while(x != y);
37     }
38     return;
39 }
40
41 inline void add(int x, int y) {
42     ++top;
43     edge[top].v = y;
44     edge[top].nex = e[x];
45     e[x] = top;
46     return;
47 }
48
49 inline bool great(std::vector<int> &x, std::vector<int> &y) {
50     if(x.size() != y.size()) {
51         return x.size() > y.size();
52     }
53     std::sort(x.begin(), x.end());
54     std::sort(y.begin(), y.end());
55     return x[0] > y[0];
56 }
57
58 int main() {
59     int m, n;
60     scanf("%d%d", &n ,&m);
61     for(int i = 1, x, y, f; i <= m; i++) {
62         scanf("%d%d%d", &x, &y, &f);
64         if(f == 2) {
66         }
67     }
68     for(int i = 1; i <= n; i++) {
69         if(!dfn[i]) {
70             tarjan(i);
71         }
72     }
73     int ans = 1;
74     for(int i = 1; i <= scc_cnt; i++) {
75         if(great(scc[i], scc[ans])) {
76             ans = i;
77         }
78     }
79     printf("%d\n", scc[ans].size());
80     std::sort(scc[ans].begin(), scc[ans].end());
81     for(int i = 0; i < scc[ans].size(); i++) {
82         printf("%d ", scc[ans][i]);
83     }
84     return 0;
85 }
AC代码

2.无向图求割点

 1 #include <cstdio>
2 #include <algorithm>
3 const int N = 100010;
4
5 struct Edge {
6     int v, nex;
7 }edge[N << 1];int top;
8 int e[N], low[N], dfn[N], num, root, ans;
9 bool cut[N];
10
11 inline void add(int x, int y) {
12     top++;
13     edge[top].v = y;
14     edge[top].nex = e[x];
15     e[x] = top;
16     return;
17 }
18
19 void tarjan(int x) {
20     dfn[x] = low[x] = ++num;
21     int t = 0;
22     for(int i = e[x]; i; i = edge[i].nex) {
23         int y = edge[i].v;
24         if(!dfn[y]) {
25             tarjan(y);
26             low[x] = std::min(low[x], low[y]);
27             if(dfn[x] <= low[y]) { /// error : > >=
28                 t++;
29             }
30         }
31         else {
32             low[x] = std::min(low[x], dfn[y]);
33         }
34     }
35     if(t > 1 || (t == 1 && x != root)) {
36         cut[x] = 1;
37         ans++;
38     }
39     return;
40 }
41
42 int main() {
43     int m, n;
44     scanf("%d%d", &n, &m);
45     for(int i = 1, x, y; i <= m; i++) {
46         scanf("%d%d", &x, &y);
49     }
50     for(int x = 1; x <= n; x++) {
51         if(!dfn[x]) {
52             root = x;
53             tarjan(x);
54         }
55     }
56     printf("%d\n", ans);
57     for(int i = 1; i <= n; i++) {
58         if(cut[i]) {
59             printf("%d ", i);
60         }
61     }
62     return 0;
63 }
AC代码

3.2_SAT

  1 #include <cstdio>
2 #include <queue>
3 #include <algorithm>
4 #include <cstring>
5
6 const int N = 210, M = 1010;
7
8 struct Edge {
9     int nex, v;
10 }edge[M << 1]; int top;
11
12 int e[N], dfn[N], low[N], tot, stk[N], t, n;
13 bool in_stk[N];
14 char s[10], w[10];
15
16 int scc_cnt, fr[N];
17
18 int chose[N];
19
20 inline bool check() {
21     for(int i = 1; i <= n; i++) {
22         if(fr[i] == fr[i + n]) {
23             return 0;
24         }
25     }
26     return 1;
27 }
28
29 inline void add(int x, int y) {
30     top++;
31     edge[top].v = y;
32     edge[top].nex = e[x];
33     e[x] = top;
34     return;
35 }
36
37 void tarjan(int x) {
38     dfn[x] = low[x] = ++tot;
39     in_stk[x] = 1;
40     stk[++t] = x;
41     for(int i = e[x]; i; i = edge[i].nex) {
42         int y = edge[i].v;
43         if(!dfn[y]) {
44             tarjan(y);
45             low[x] = std::min(low[x], low[y]);
46         }
47         else if(in_stk[y]) {
48             low[x] = std::min(low[x], dfn[y]);
49         }
50     }
51     if(low[x] == dfn[x]) {
52         scc_cnt++;
53         int y;
54         do {
55             y = stk[t--];
56             fr[y] = scc_cnt;
57             in_stk[y] = 0;
58         } while(y != x);
59     }
60     return;
61 }
62
63 inline void clear() {
64     top = 0;
65     tot = 0;
66     scc_cnt = 0;
67     memset(e, 0, sizeof(e));
68     memset(dfn, 0, sizeof(dfn));
69     memset(low, 0, sizeof(low));
70     memset(chose, 0, sizeof(chose));
71     return;
72 }
73
75     char c = getchar();
76     while(c != 'h' && c != 'm') {
77         c = getchar();
78     }
79     int x;
80     scanf("%d", &x);
81     if(c == 'm') {
82         x += n;
83     }
84     return x;
85 }
86
87 inline int _(int x) { // opposite
88     if(x > n) {
89         return x - n;
90     }
91     return x + n;
92 }
93
94 int main() {
95     int T;
96     scanf("%d", &T);
97     while(T--) {
98         int m;
99         scanf("%d%d", &n, &m);
100         for(int i = 1; i <= m; i++) {
105         }
106
107         for(int i = 1; i <= (n << 1); i++) {
108             if(!dfn[i]) {
109                 tarjan(i);
110             }
111         }
112
113         if(check()) {
114             printf("GOOD\n");
115         }
116         else {
118         }
119         clear();
120     }
121
122     return 0;
123 }

Naive方法水过的模板题：

 1 #include <cstdio>
2 #include <algorithm>
3
4 const int N = 1000010;
5
6 struct Edge {
7     int nex, v;
8 }edge[N << 1]; int top;
9
10 int e[N << 1], stk[N << 1], t, n;
11 bool vis[N << 1];
12
13 inline void add(int x, int y) {
14     top++;
15     edge[top].v = y;
16     edge[top].nex = e[x];
17     e[x] = top;
18     return;
19 }
20
21 inline int _(int x) {
22     return x > n ? x - n : x + n;
23 }
24
25 bool DFS(int x) {
26     if(vis[_(x)]) {
27         return 0;
28     }
29     if(vis[x]) {
30         return 1;
31     }
32     stk[++t] = x;
33     vis[x] = 1;
34     for(int i = e[x]; i; i = edge[i].nex) {
35         int y = edge[i].v;
36         if(!DFS(y)) {
37             return 0;
38         }
39     }
40     return 1;
41 }
42
43 int main() {
44     int m;
45     scanf("%d%d", &n, &m);
46     for(int i = 1, x, y, z, w; i <= m; i++) {
47         scanf("%d%d%d%d", &x, &y, &z, &w);
48         add(x + (y ^ 1) * n, z + w * n);
49         add(z + (w ^ 1) * n, x + y * n);
50     }
51
52     for(int i = 1; i <= n; i++) {
53         if(!vis[i] && !vis[i + n]) {
54             t = 0;
55             if(!DFS(i)) {
56                 while(t) {
57                     vis[stk[t]] = 0;
58                     t--;
59                 }
60                 if(!DFS(i + n)) {
61                     printf("IMPOSSIBLE");
62                     return 0;
63                 }
64             }
65         }
66     }
67     printf("POSSIBLE\n");
68     for(int i = 1; i <= n; i++) {
69         printf("%d ", vis[i + n]);
70     }
71     return 0;
72 }

posted @ 2018-07-21 17:14  garage  阅读(...)  评论(...编辑  收藏