# BZOJ1977: [BeiJing2010组队]次小生成树 Tree

## 1977: [BeiJing2010组队]次小生成树 Tree

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 3514  Solved: 941
[Submit][Status][Discuss]

5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6

11

## Source

【题解】

  1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <cstdlib>
5 #include <algorithm>
6 #include <queue>
7 #include <vector>
8 #include <map>
9 #include <string>
10 #include <cmath>
11 #define min(a, b) ((a) < (b) ? (a) : (b))
12 #define max(a, b) ((a) > (b) ? (a) : (b))
13 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
14 template<class T>
15 inline void swap(T &a, T &b)
16 {
17     T tmp = a;a = b;b = tmp;
18 }
19 inline void read(long long &x)
20 {
21     x = 0;char ch = getchar(), c = ch;
22     while(ch < '0' || ch > '9') c = ch, ch = getchar();
23     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
24     if(c == '-') x = -x;
25 }
26
27 const long long INF = 0x3f3f3f3f3f3f3f3f;
28 const long long MAXN = 500000 + 10;
29 const long long MAXM = 500000 + 10;
30
31 long long u[MAXM],v[MAXM],w[MAXM],cnt[MAXM],n,m,fa[MAXN],tot,f1,f2,M,vis[MAXM];
32 long long cmp(long long a, long long b)
33 {
34     return w[a] < w[b];
35 }
36 long long find(long long x)
37 {
38     return x == fa[x] ? x : fa[x] = find(fa[x]);
39 }
40 struct Edge
41 {
42     long long u,v,w,nxt;
43     Edge(long long _u, long long _v, long long _w, long long _nxt){u = _u;v = _v;w = _w;nxt = _nxt;}
44     Edge(){}
45 }edge[MAXN << 1];
47 inline void insert(long long a, long long b, long long c)
48 {
51 }
52
53 //p[0]表示跳到哪个节点，p[1]表示最大值，p[2]表示次大值
54 long long p[3][30][MAXN], deep[MAXN];
55 void dfs(long long x, long long pre)
56 {
57     for(long long pos = head[x];pos;pos = edge[pos].nxt)
58     {
59         long long v = edge[pos].v;
60         if(v == pre) continue;
61         p[0][0][v] = x, p[1][0][v] = edge[pos].w;deep[v] = deep[x] + 1, dfs(v, x);
62     }
63 }
64 void yuchuli()
65 {
66     memset(p[1], -1, sizeof(p[1]));
67     memset(p[2], -1, sizeof(p[2]));
68     dfs(1, -1);
69     for(M = 0;(1 << M) <= n;++ M); -- M;
70     for(long long i = 1;i <= M;++ i)
71         for(long long j = 1;j <= n;++ j)
72             p[0][i][j] = p[0][i - 1][p[0][i - 1][j]];
73     for(long long i = 1;i <= M;++ i)
74         for(long long j = 1;j <= n;++ j)
75             if(deep[j] >= (1 << i))
76             {
77                 long long tmp1 = p[1][i - 1][j], tmp2 = p[1][i - 1][p[0][i - 1][j]];
78                 if(tmp1 == tmp2) p[2][i][j] = max(p[2][i - 1][j], p[2][i - 1][p[0][i - 1][j]]), p[1][i][j] = tmp1;
79                 else if(tmp1 > tmp2) p[2][i][j] = max(tmp2, p[2][i - 1][j]), p[1][i][j] = tmp1;
80                 else p[2][i][j] = max(tmp1, p[2][i - 1][p[0][i - 1][j]]), p[1][i][j] = tmp2;
81             }
82 }
83 long long LCA(long long u, long long v)
84 {
85     if(deep[u] < deep[v]) swap(u, v);
86     for(long long i = M;i >= 0;-- i)
87         if(deep[u] >= deep[v] + (1 << i))
88             u = p[0][i][u];
89     if(u == v) return u;
90     for(long long i = M;i >= 0;-- i)
91         if(p[0][i][u] != p[0][i][v])
92             u = p[0][i][u], v = p[0][i][v];
93     return p[0][0][u];
94 }
95 //v为lca
96 void lian(long long &ma, long long &cima, long long u, long long v)
97 {
98     ma = cima = -1;
99     for(long long i = M;i >= 0;-- i)
100         if(deep[u] >= deep[v] + (1 << i))
101         {
102             if(ma < p[1][i][u]) cima = max(ma, p[2][i][u]), ma = p[1][i][u];
103             else if(ma > p[1][i][u]) cima = max(cima, p[1][i][u]);
104             else cima = max(cima, p[2][i][u]);
105             u = p[0][i][u];
106         }
107 }
108
109 void find(long long &ma, long long &cima, long long u, long long v)
110 {
111     long long lca = LCA(u, v);
112     long long lma, lcima, rma, rcima;
113     lian(lma, lcima, u, lca), lian(rma, rcima, v, lca);
114     ma = max(lma, rma);
115     if(lma > rma) cima = max(rma, lcima);
116     else if(lma < rma) cima = max(lma, rcima);
117     else cima = max(lcima, rcima);
118 }
119
120 long long ans, ans2;
121 int main()
122 {
125     for(long long i = 1;i <= n;++ i) fa[i] = i;
126     std::sort(cnt + 1, cnt + 1 + m, cmp);
127     for(long long i = 1;i <= m;++ i)
128     {
129         f1 = find(u[cnt[i]]), f2 = find(v[cnt[i]]);
130         if(f1 == f2) continue;
131         ++ tot;insert(u[cnt[i]], v[cnt[i]], w[cnt[i]]), insert(v[cnt[i]], u[cnt[i]], w[cnt[i]]);
132         fa[f1] = f2; vis[cnt[i]] = 1;ans += w[cnt[i]];
133         if(tot == n - 1) break;
134     }
135     yuchuli();ans2 = INF;
136     for(long long i = 1;i <= m;++ i)
137     {
138         if(vis[i]) continue;
139         long long ma,cima;
140         find(ma, cima, u[i], v[i]);
141         if(w[i] != ma) ans2 = min(ans2, ans + (w[i] - ma));
142         else ans2 = min(ans2, ans + (w[i] - cima));
143     }
144     printf("%lld\n", ans2);
145     return 0;
146 }
BZOJ1977

posted @ 2018-01-29 16:20  嘒彼小星  阅读(180)  评论(0编辑  收藏  举报