# 点分治

1.找根

2.进行统计，看情况需要1/2次DFS，还要记录一些东西。

3.清空，对每个子树进行点分治。

  1 #include <cstdio>
2 #include <algorithm>
3 #define say(a) printf(#a), printf(" = %d \n", a)
4 const int N = 20010, INF = 0x3f3f3f3f;
5
6 struct Edge {
7     int nex, v, len;
8 }edge[N << 1]; int top;
9
10 int e[N], d[N], fr[N], siz[N], fa[N];
11 bool del[N];
12 int n_, root_, small, ans, sum[3], sum_[3];
13
14 inline void add(int x, int y, int z) {
15     edge[++top].v = y;
16     edge[top].len = z;
17     edge[top].nex = e[x];
18     e[x] = top;
19     return;
20 }
21
22 int getroot(int x, int f) {
23     siz[x] = 1;
24     int large = 0;
25     for(int i = e[x]; i; i = edge[i].nex) {
26         int y = edge[i].v;
27         if(y == f || del[y]) {
28             continue;
29         }
30         int temp = getroot(y, x);
31         siz[x] += temp;
32         large = std::max(large, temp);
33     }
34     if(std::max(large, n_ - siz[x]) < small) {
35         small = std::max(large, n_ - siz[x]);
36         root_ = x;
37     }
38     return siz[x];
39 }
40
41 void DFS_1(int x, int f) {
42     fa[x] = f;
43     for(int i = e[x]; i; i = edge[i].nex) {
44         int y = edge[i].v;
45         if(y == fa[x] || del[y]) {
46             continue;
47         }
48         d[y] = d[x] + edge[i].len;
49         sum_[d[y] % 3]++;
50         //fr[y] = fr[x];
51         DFS_1(y, x);
52     }
53     return;
54 }
55
56 void poi_div(int root) {
57     sum[0] = sum[1] = sum[2] = 0;
58     sum[0] = 1;
59     small = INF;
60     getroot(root, 0);
61     root = root_;
62     for(int i = e[root]; i; i = edge[i].nex) {
63         int y = edge[i].v;
64         if(del[y]) {
65             continue;
66         }
67         d[y] = edge[i].len;
68         sum_[d[y] % 3]++;
69         fr[y] = y;
70         DFS_1(y, root); /// get d[], fa[]
71         ans += sum_[0] * sum[0];
72         ans += sum_[1] * sum[2];
73         ans += sum_[2] * sum[1];
74
75         for(int i = 0; i < 3; i++) {
76             sum[i] += sum_[i];
77             sum_[i] = 0;
78         }
79     }
80     del[root] = 1;
81     for(int i = e[root]; i; i = edge[i].nex) {
82         int y = edge[i].v;
83         if(del[y]) {
84             continue;
85         }
86         n_ = siz[y];
87         poi_div(y);
88     }
89     return;
90 }
91
92 int gcd(int x, int y) {
93     if(!y) {
94         return x;
95     }
96     return gcd(y, x % y);
97 }
98
99 int main() {
100     int n;
101     scanf("%d", &n);
102     for(int i = 1, x, y, z; i < n; i++) {
103         scanf("%d%d%d", &x, &y, &z);
106     }
107     n_ = n;
108     poi_div(1);
109
110     ans <<= 1;
111     ans += n;
112     int g = gcd(ans, n * n);
113     printf("%d/%d", ans / g, n * n / g);
114
115     return 0;
116 }
AC代码

  1 #include <cstdio>
2 #include <algorithm>
3 #include <cstring>
4 #define say(a) printf(#a), printf(" = %d \n", a)
5 typedef long long LL;
6
7 const int N = 40005, INF = 0x3f3f3f3f;
8
9 struct Edge {
10     int v, nex, len;
11 }edge[N << 1]; int top;
12
13 int e[N], fa[N], fr[N], siz[N], cnt[N], t[N];
14 bool del[N];
15 int n_, root_, small, tt, ans;
16 LL d[N], k;
17
18 inline bool cmp(int x, int y) {
19     return d[x] < d[y];
20 }
21
22 inline void add(int x, int y, int z) {
23     edge[++top].v = y;
24     edge[top].nex = e[x];
25     edge[top].len = z;
26     e[x] = top;
27     return;
28 }
29
30 int getroot(int x, int f) {
31     siz[x] = 1;
32     int large = 0;
33     for(int i = e[x]; i; i = edge[i].nex) {
34         int y = edge[i].v;
35         if(y == f || del[y]) {
36             continue;
37         }
38         int temp = getroot(y, x);
39         siz[x] += temp;
40         large = std::max(large, temp);
41     }
42     if(std::max(large, n_ - siz[x]) < small) {
43         small = std::max(large, n_ - siz[x]);
44         root_ = x;
45     }
46     return siz[x];
47 }
48
49 void DFS_1(int x, int f) {
50     fa[x] = f;
51     t[++tt] = x;
52     cnt[fr[x]]++;
53     for(int i = e[x]; i; i = edge[i].nex) {
54         int y = edge[i].v;
55         if(y == fa[x] || del[y]) {
56             continue;
57         }
58         fr[y] = fr[x];
59         d[y] = d[x] + edge[i].len;
60         ans += (d[y] <= k);
61         DFS_1(y, x);
62     }
63     return;
64 }
65
66 void poi_div(int x) {
67     small = INF;
68     getroot(x, 0);
69     x = root_;
70     for(int i = e[x]; i; i = edge[i].nex) {
71         int y = edge[i].v;
72         if(del[y]) {
73             continue;
74         }
75         fr[y] = y;
76         d[y] = edge[i].len;
77         ans += (d[y] <= k); /// way that one point is root
78         DFS_1(y, x); /// get d[] fa[] fr[]   insert t[]
79     }
80     //cal
81     std::sort(t + 1, t + tt + 1, cmp);
82     int l = 1, r = tt; /// cnt[]  [l + 1, r]
83     cnt[fr[t[1]]]--;
84     while(l < r) {
85         while(l < r && d[t[l]] + d[t[r]] > k) {
86             cnt[fr[t[r]]]--;
87             r--;
88         }
89         if(l == r) {
90             break;
91         }
92         ans += (r - l - cnt[fr[t[l]]]); /// cal
93         l++;
94         cnt[fr[t[l]]]--;
95     }
96     cnt[fr[t[l]]] = 0; /// here !!
97     /// pay attentions !! above may error
98     tt = 0;
99     del[x] = 1;
100     for(int i = e[x]; i; i = edge[i].nex) {
101         int y = edge[i].v;
102         if(del[y]) {
103             continue;
104         }
105         n_ = siz[y];
106         poi_div(y);
107     }
108
109     return;
110 }
111
112 int main() {
113     int n;
114     scanf("%d", &n);
115     for(int i = 1, x, y, z; i < n; i++) {
116         scanf("%d%d%d", &x, &y, &z);
119     }
120     scanf("%lld", &k);
121
122     n_ = n;
123     poi_div(1);
124
125     printf("%d", ans);
126
127     return 0;
128 }
AC代码

  1 #include <cstdio>
2 #include <set>
3 #include <algorithm>
4
5 const int N = 30010, INF = 0x3f3f3f3f;
6
7 struct Edge {
8     int nex, v;
9     int len, val;
10 }edge[N << 1]; int top;
11
12 struct Node {
13     int d, val;
14     Node(int dis = 0, int value = 0) {
15         d = dis;
16         val = value;
17     }
18     inline bool operator <(const Node &w) const {
19         return d < w.d;
20     }
21 }node[N]; int t;
22
23 int L, ans;
24 int siz[N], num, small, root; // point divided
25 int e[N];
26 bool del[N];
27
28 std::set<Node> st;
29
30 inline bool cmp(const Node &a, const Node &b) {
31     return a.d > b.d;
32 }
33
34 inline void add(int x, int y, int z, int w) {
35     top++;
36     edge[top].v = y;
37     edge[top].len = z;
38     edge[top].val = w;
39     edge[top].nex = e[x];
40     e[x] = top;
41     return;
42 }
43
44 void getroot(int x, int f) {
45     siz[x] = 1;
46     int large = -1;
47     for(int i = e[x]; i; i = edge[i].nex) {
48         int y = edge[i].v;
49         if(y == f || del[y]) {
50             continue;
51         }
52         getroot(y, x);
53         large = std::max(large, siz[y]);
54         siz[x] += siz[y];
55     }
56     large = std::max(large, num - siz[x]);
57     if(large < small) {
58         small = large;
59         root = x;
60     }
61     return;
62 }
63
64 void DFS_1(int x, int f, int s, int v) {
65     if(s > L) {
66         return;
67     }
68     ans = std::max(ans, v);
69     node[++t] = Node(s, v);
70     for(int i = e[x]; i; i = edge[i].nex) {
71         int y = edge[i].v;
72         if(del[y] || y == f) {
73             continue;
74         }
75         DFS_1(y, x, s + edge[i].len, v + edge[i].val);
76     }
77     return;
78 }
79
80 void poi_div(int x) {
81     small = INF;
82     getroot(x, 0);
83     x = root;
84
85     st.clear();
86     for(int i = e[x]; i; i = edge[i].nex) {
87         int y = edge[i].v;
88         if(del[y]) {
89             continue;
90         }
91
92         t = 0;
93         DFS_1(y, x, edge[i].len, edge[i].val);
94
95         // cal ans
96         std::sort(node + 1, node + t + 1, cmp);
97         std::set<Node>::iterator it = st.begin();
98         int large = 0; // error  -1
99         for(int i = 1; i <= t; i++) {
100             while(it != st.end() && (*it).d + node[i].d <= L) {
101                 large = std::max(large, (*it).val);
102                 it++;
103             }
104             ans = std::max(ans, large + node[i].val);
105         }
106
107         //merge  y
108         for(int i = 1; i <= t; i++) {
109             st.insert(node[i]);
110         }
111     }
112
113     del[x] = 1;
114     for(int i = e[x]; i; i = edge[i].nex) {
115         int y = edge[i].v;
116         if(del[y]) {
117             continue;
118         }
119         num = siz[y];
120         poi_div(y);
121     }
122     return;
123 }
124
125 int main() {
126     int n, m;
127     scanf("%d%d%d", &n, &m, &L);
128     for(int i = 1, x, y, z, w; i <= m; i++) {
129         scanf("%d%d%d%d", &x, &y, &z, &w);
132     }
133
134     num = n;
135     poi_div(1);
136
137     printf("%d", ans);
138     return 0;
139 }
AC代码

loj#2013 点分治 + 线性基合并。

posted @ 2018-09-20 18:01  huyufeifei  阅读(...)  评论(...编辑  收藏