# 【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并

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

11

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
#define M 1000000000
#define inf 0x7f7f7f7f
using namespace std;
struct data
{
int x , y , z;
bool operator<(const data &a)const {return z < a.z;}
}a[N * 3];
int f[N] , flag[N * 3] , head[N] , to[N << 1] , len[N << 1] , next[N << 1] , cnt , fa[N][20] , deep[N] , val[N] , log[N];
int ls[N << 7] , rs[N << 7] , si[N << 7] , mx[N << 7] , sx[N << 7] , tot , root[N] , ans = inf;
int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
}
inline void add(int x , int y , int z)
{
to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
}
void dfs(int x)
{
int i;
for(i = 1 ; (1 << i) <= deep[x] ; i ++ ) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for(i = head[x] ; i ; i = next[i])
if(to[i] != fa[x][0])
fa[to[i]][0] = x , deep[to[i]] = deep[x] + 1 , val[to[i]] = len[i] , dfs(to[i]);
}
inline int lca(int x , int y)
{
int i;
if(deep[x] < deep[y]) swap(x , y);
for(i = log[deep[x] - deep[y]] ; ~i ; i -- )
if(deep[x] - deep[y] >= (1 << i))
x = fa[x][i];
if(x == y) return x;
for(i = log[deep[x]] ; ~i ; i -- )
if(deep[x] >= (1 << i) && fa[x][i] != fa[y][i])
x = fa[x][i] , y = fa[y][i];
return fa[x][0];
}
void pushup(int x)
{
if(mx[ls[x]] == inf) mx[x] = mx[rs[x]] , sx[x] = sx[rs[x]];
else if(sx[ls[x]] == inf) mx[x] = mx[ls[x]] , sx[x] = mx[rs[x]];
else mx[x] = mx[ls[x]] , sx[x] = sx[ls[x]];
}
void update(int p , int a , int l , int r , int &x)
{
if(!x) x = ++tot;
if(l == r)
{
si[x] += a;
if(si[x] > 0) mx[x] = l;
else mx[x] = inf;
return;
}
int mid = (l + r) >> 1;
if(p <= mid) update(p , a , l , mid , ls[x]);
else update(p , a , mid + 1 , r , rs[x]);
pushup(x);
}
int merge(int l , int r , int x , int y)
{
if(!x) return y;
if(!y) return x;
if(l == r)
{
si[x] += si[y];
if(si[x] > 0) mx[x] = l;
else mx[x] = inf;
return x;
}
int mid = (l + r) >> 1;
ls[x] = merge(l , mid , ls[x] , ls[y]);
rs[x] = merge(mid + 1 , r , rs[x] , rs[y]);
pushup(x);
return x;
}
void solve(int x)
{
int i;
for(i = head[x] ; i ; i = next[i])
if(to[i] != fa[x][0])
solve(to[i]) , root[x] = merge(1 , M , root[x] , root[to[i]]);
if(mx[root[x]] != inf)
{
if(mx[root[x]] != val[x]) ans = min(ans , mx[root[x]] - val[x]);
else if(sx[root[x]] != inf) ans = min(ans , sx[root[x]] - val[x]);
}
}
int main()
{
int n , m , i;
long long sum = 0;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d" , &a[i].x , &a[i].y , &a[i].z);
sort(a + 1 , a + m + 1);
log[0] = -1;
for(i = 1 ; i <= n ; i ++ ) f[i] = i , log[i] = log[i >> 1] + 1;
for(i = 1 ; i <= m ; i ++ )
if(find(a[i].x) != find(a[i].y))
f[f[a[i].x]] = f[a[i].y] , add(a[i].x , a[i].y , a[i].z) , add(a[i].y , a[i].x , a[i].z) , sum += a[i].z , flag[i] = 1;
dfs(1);
memset(mx , 0x7f , sizeof(mx)) , memset(sx , 0x7f , sizeof(sx));
for(i = 1 ; i <= m ; i ++ )
if(!flag[i])
update(a[i].z , 1 , 1 , M , root[a[i].x]) , update(a[i].z , 1 , 1 , M , root[a[i].y]) , update(a[i].z , -2 , 1 , M , root[lca(a[i].x , a[i].y)]);
solve(1);
printf("%lld\n" , sum + ans);
return 0;
}


|转载请注明 [原文链接][作者] ，谢谢！

posted @ 2017-10-23 19:07  GXZlegend  阅读(422)  评论(0编辑  收藏  举报