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

  1 /**************************************************************
2     Problem: 1977
3     User: rausen
4     Language: C++
5     Result: Accepted
6     Time:1740 ms
7     Memory:32628 kb
8 ****************************************************************/
9
10 #include <cstdio>
11 #include <algorithm>
12
13 using namespace std;
14 typedef long long ll;
15 const int N = 100001;
16 const int M = 300001;
17 struct data{
18     int x, y, v;
19     bool selected;
20 }a[M];
21 struct edge{
22     int next, to ,v;
23 }e[N * 2];
24 struct tree_node{
25     int dep, fa[17], d1[17], d2[17];
26 }tr[N];
27 inline bool operator < (const data a, const data b){
28     return a.v < b.v;
29 }
30
31 int n, m, cnt, tot, del = 1e9;
32 int first[N], fa[N];
33 ll ans;
34
36     int x = 0, sgn = 1;
37     char ch = getchar();
38     while (ch < '0' || ch > '9'){
39         if (ch == '-') sgn = -1;
40         ch = getchar();
41     }
42     while (ch >= '0' && ch <= '9'){
43         x = x * 10 + ch - '0';
44         ch = getchar();
45     }
46     return sgn * x;
47 }
48
49 inline void add_edge(int x, int y, int z){
50     e[++tot].next = first[x], first[x] = tot;
51     e[tot].to = y, e[tot].v = z;
52 }
53
54 void add_Edges(int X, int Y, int Z){
57 }
58
59 int find_fa(int x){
60     return x == fa[x] ? x : fa[x] = find_fa(fa[x]);
61 }
62
63 void dfs(int p){
64     int i, x, y, FA;
65     for (i = 1; i <= 16; ++i){
66         if (tr[p].dep < (1 << i)) break;
67         FA = tr[p].fa[i - 1];
68         tr[p].fa[i] = tr[FA].fa[i - 1];
69         tr[p].d1[i] = max(tr[p].d1[i - 1], tr[FA].d1[i - 1]);
70         if (tr[p].d1[i - 1] == tr[FA].d1[i - 1])
71             tr[p].d2[i] = max(tr[p].d2[i - 1], tr[FA].d2[i - 1]);
72         else {
73             tr[p].d2[i] = min(tr[p].d1[i - 1], tr[FA].d1[i - 1]);
74             tr[p].d2[i] = max(tr[p].d2[i - 1], tr[p].d2[i]);
75             tr[p].d2[i] = max(tr[p].d2[i], tr[FA].d2[i - 1]);
76         }
77     }
78     for (x = first[p]; x; x = e[x].next)
79         if ((y = e[x].to) != tr[p].fa[0]){
80             tr[y].fa[0] = p, tr[y].d1[0] = e[x].v, tr[y].dep = tr[p].dep + 1;
81             dfs(y);
82         }
83 }
84
85 inline int lca(int x, int y){
86     if (tr[x].dep < tr[y].dep) swap(x, y);
87     int tmp = tr[x].dep - tr[y].dep, i;
88     for (i = 0; i <= 16; ++i)
89         if ((1 << i) & tmp) x = tr[x].fa[i];
90     for (i = 16; i >= 0; --i)
91         if (tr[x].fa[i] != tr[y].fa[i])
92             x = tr[x].fa[i], y = tr[y].fa[i];
93     return x == y ? x : tr[x].fa[0];
94 }
95
96 void calc(int x, int f, int v){
97     int mx1 = 0, mx2 = 0, tmp = tr[x].dep - tr[f].dep, i;
98     for (i = 0; i <= 16; ++i)
99         if ((1 << i) & tmp){
100             if (tr[x].d1[i] > mx1)
101                 mx2 = mx1, mx1 = tr[x].d1[i];
102             mx2 = max(mx2, tr[x].d2[i]);
103             x = tr[x].fa[i];
104         }
105     del = min(del, mx1 == v ? v - mx2 : v - mx1);
106 }
107
108 void work(int t, int v){
109     int x = a[t].x, y = a[t].y, f = lca(x, y);
110     calc(x, f, v);
111     calc(y, f, v);
112 }
113
114 int main(){
116     int i, f1, f2, TOT = 0;
117     for (i = 1; i <= m; ++i)
119     for (i = 1; i <= n; ++i)
120         fa[i] = i;
121     sort(a + 1, a + m + 1);
122     for (i = 1; i <= m; ++i)
123         if ((f1 = find_fa(a[i].x)) != (f2 = find_fa(a[i].y))){
124             fa[f1] = f2;
125             ans += a[i].v;
126             a[i].selected = 1;
128             ++TOT;
129             if (TOT == n - 1) break;
130         }
131     dfs(1);
132     for (i = 1; i <= m; ++i)
133         if (!a[i].selected)
134             work(i, a[i].v);
135     printf("%lld\n", ans + del);
136     return 0;
137 }
View Code

By Xs酱~ 转载请说明 博客地址：http://www.cnblogs.com/rausen
posted on 2014-10-31 22:30  Xs酱~  阅读(209)  评论(0编辑  收藏  举报