题意
填边使得树的两点之间距离可以遍历 1 t o 2 n 2 9 1\quad to\quad\frac{2n^2}{9} 1to92n2所有整数。
题解
证明
1
分配数字给边,对于一棵树,如果要使得根节点到每个点的距离分别为
a
1
,
a
2
,
a
3
,
.
.
.
,
a
n
a_1,a_2,a_3,...,a_n
a1,a2,a3,...,an
有这样的解决方法,首先分配最上面的结点即根节点的孩子,
a
1
a_1
a1到
a
k
a_k
ak,对于这些孩子的孩子,分别是
a
k
+
1
−
a
1
a_{k+1}-a_1
ak+1−a1,减去前面的前缀和即可,只要你保证,是排好序的,这样就不会出现负值。
2
对于以重心为根节点的树,你的每棵子树节点数都
≤
n
2
\leq \frac{n}{2}
≤2n
我们能否分成两部分,每一部分都有至少
1
3
\frac{1}{3}
31的结点。
我们分离的时候,排序子树大小,选前
k
k
k个刚好大于等于
n
−
1
3
\frac{n-1}{3}
3n−1。
刚好不满足的左边子树大小和是
L
L
L,
x
x
x是加上满足了,
R
R
R是右边的
即
L
≤
1
/
3
,
L
+
x
≥
1
/
3
,
R
≥
x
,
L
+
x
+
R
=
n
−
1
L\leq 1/3,L+x \geq1/3,R \geq x,L+x+R=n-1
L≤1/3,L+x≥1/3,R≥x,L+x+R=n−1
显然
R
≥
n
−
1
/
3
R\geq n-1/3
R≥n−1/3
3
在满足了第
1
,
2
1,2
1,2点,我们就可以分成左右部分
a
a
a、
b
b
b。
左边的距离是
1
,
.
.
.
,
a
1,...,a
1,...,a,右边的距离是
(
a
+
1
)
,
2
(
a
+
1
)
,
.
.
.
,
b
(
a
+
1
)
(a+1),2(a+1),...,b(a+1)
(a+1),2(a+1),...,b(a+1)
左边表示的距离是
1
,
.
.
.
a
1,...a
1,...a。
右边第一个,
a
+
1
a+1
a+1,结合左边之后,
a
+
2
,
.
.
.
,
2
a
+
1
a+2,...,2a+1
a+2,...,2a+1,刚好接上第二个。
最后能表示的距离是,
(
b
+
1
)
(
a
+
1
)
−
1
(b+1)(a+1)-1
(b+1)(a+1)−1,因为
a
≥
n
−
1
3
a\geq \frac{n-1}{3}
a≥3n−1,
b
≥
n
−
1
3
,
a
+
b
=
n
−
1
b\geq \frac{n-1}{3},a+b=n-1
b≥3n−1,a+b=n−1
最小的距离是:
(
n
−
1
+
3
)
(
2
n
−
2
+
3
)
9
−
1
≥
2
n
2
9
\frac{(n-1+3)(2n-2+3)}{9}-1\geq \frac{2n^2}{9}
9(n−1+3)(2n−2+3)−1≥92n2
根据以上三点,其实好像 1 1 1、 3 3 3就够了,但是要证明满足了 1 3 \frac{1}{3} 31,右边还存在子树,所以…
接下来就是先求重心,算子树大小,排序,分别把左右的处理了即可。
#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define sf(x) scanf("%d",&x)
#define inf 1e18
using namespace std;
typedef long long ll;
const int maxn = 405000;
vector<int>G[maxn];
int n,sz[maxn],mx=0x3f3f3f3f,rt=0;
int val[maxn];
void dfs1(int u,int fa){
sz[u]=1;
int tmp=0;
for(auto v:G[u]){
if(v==fa)continue;
dfs1(v,u);
tmp=max(tmp,sz[v]);
sz[u]+=sz[v];
}
tmp=max(tmp,n-sz[u]);
if(tmp<mx){
mx=tmp;
rt=u;
}
}
void dfs2(int u,int fa){
sz[u]=1;
for(auto v:G[u]){
if(v==fa)continue;
dfs2(v,u);
sz[u]+=sz[v];
}
}
int base,tot;
pair<int,int>p[maxn];
void dfs(int u,int fa){
cout<<fa<<" "<<u<<" "<<tot*base-val[fa]<<endl;
val[u]=tot*base;
tot++;
for(auto v:G[u]){
if(v==fa)continue;
dfs(v,u);
}
}
int main(){
cin>>n;
FOR(i,1,n-1){
int u,v;
sf(u),sf(v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs1(1,-1),dfs2(rt,-1);
FOR(i,1,G[rt].size())p[i]=make_pair(sz[G[rt][i-1]],G[rt][i-1]);
int m=G[rt].size();
sort(p+1,p+1+m);
int mid=0,ret=0;
FOR(i,1,m){
ret+=p[i].first;
if(ret>=(n-1)/3){
mid=i;
break;
}
}
//FOR(i,1,m)cout<<p[i].second<<" "<<p[i].first<<endl;
//cout<<rt<<endl;
tot=1,base=1;
FOR(i,1,mid)dfs(p[i].second,rt);
tot=1,base=ret+1;
FOR(i,mid+1,m)dfs(p[i].second,rt);
}