卧薪尝胆,厚积薄发。
USACO2018OPEN PLATINUM Disruption
Date: Mon Sep 17 16:02:35 CST 2018 In Category: NoCategory

Description:

给一棵树和若干条带权非树边,问删掉一条树边后能将两部分连起来的边权最小的非树边权值是多少。
$1\le n \le 50000$

Solution:

对于一条非树边,把它加进树中后会形成一个环,那么对于这个环上的所有树边删掉后都可以用这条边连起来,于是就变成了一个树上的一条路径和一个数取 $\min$ ,可以用树链剖分来实现。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
inline int read()
{
register int res = 0;
register char c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res;
}
int n,m;
#define MAXN 100010
#define INF 0x3f3f3f3f
struct edge
{
int to,nxt;
}e[MAXN << 1];
int edgenum = 0;
int lin[MAXN] = {0};
inline void add(int a,int b)
{
++edgenum;e[edgenum].to = b;e[edgenum].nxt = lin[a];lin[a] = edgenum;
++edgenum;e[edgenum].to = a;e[edgenum].nxt = lin[b];lin[b] = edgenum;
return;
}
int fa[MAXN],dep[MAXN],top[MAXN],siz[MAXN],son[MAXN],rnk[MAXN],th[MAXN],tot = 0;
void dfs1(int k,int depth)
{
siz[k] = 1;dep[k] = depth;
for(register int i = lin[k];i != 0;i = e[i].nxt)
{
if(e[i].to != fa[k])
{
fa[e[i].to] = k;
dfs1(e[i].to,depth + 1);
siz[k] += siz[e[i].to];
if(son[k] == 0 || siz[e[i].to] > siz[son[k]])
{
son[k] = e[i].to;
}
}
}
return;
}
void dfs2(int k,int tp)
{
top[k] = tp;
rnk[k] = ++tot;th[tot] = k;
if(son[k] == 0)return;
dfs2(son[k],tp);
for(register int i = lin[k];i != 0;i = e[i].nxt)
{
if(e[i].to != fa[k] && e[i].to != son[k])
{
dfs2(e[i].to,e[i].to);
}
}
return;
}
struct node
{
int lc,rc;
int tag;
node(){tag = INF;}
}t[MAXN << 1];
int ptr = 0;
inline int newnode(){return ++ptr;}
int root;
#define mid ((l + r) >> 1)
void build(int &rt,int l,int r)
{
rt = newnode();
if(l == r)return;
build(t[rt].lc,l,mid);
build(t[rt].rc,mid + 1,r);
return;
}
void set(int rt,int L,int R,int k,int l,int r)
{
if(k >= t[rt].tag)return;
if(L <= l && r <= R)
{
t[rt].tag = k;
return;
}
if(L <= mid)set(t[rt].lc,L,R,k,l,mid);
if(R > mid)set(t[rt].rc,L,R,k,mid + 1,r);
return;
}
inline void work(int a,int b,int c)
{
while(top[a] != top[b])
{
if(dep[top[a]] < dep[top[b]])swap(a,b);
set(root,rnk[top[a]],rnk[a],c,1,n * 2 - 1);
a = fa[top[a]];
}
if(dep[a] > dep[b])swap(a,b);
set(root,rnk[a],rnk[b],c,1,n * 2 - 1);
return;
}
int ans[MAXN];
void dfs(int rt,int l,int r,int k)
{
k = min(k,t[rt].tag);
if(l == r)
{
ans[l] = k;
return;
}
dfs(t[rt].lc,l,mid,k);
dfs(t[rt].rc,mid + 1,r,k);
return;
}
int main()
{//freopen("testdata.in","r",stdin);freopen("kkk.out","w",stdout);
scanf("%d%d",&n,&m);
int a,b,c;
for(int i = 1;i < n;++i)
{
a = read();b = read();
add(a,i + n);add(b,i + n);
}
dfs1(1,1);dfs2(1,1);
build(root,1,n * 2 - 1);
for(int i = 1;i <= m;++i)
{
a = read();b = read();c = read();
work(a,b,c);
}
dfs(root,1,n * 2 - 1,INF);
for(int i = 1;i < n;++i)
{
if(ans[rnk[i + n]] == INF)puts("-1");
else printf("%d\n",ans[rnk[i + n]]);
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡