CF1338B Edge Weight Assignment
CF1338B Edge Weight Assignment
对于最小值,
肯定能猜到答案不会太大,画几个图之后发现,单独考虑一条链时,若链长(这里指节点数减 \(1\))为偶数,全填一个数就搞定了,若为奇数,需要至少 \(3\) 个数,比如一堆 \(1\),一个 \(2\),一个 \(3\) 就可以消掉。
推广到一般的树上,只要有叶子间距离全为偶数,那答案为 \(1\),否则答案为 \(3\)。
对于最大值,
容易发现父亲相同的一堆叶子与父亲的边权必须是一样的。
再注意到边权可以随便赋,所以就该大胆猜除了上面这种情况,其他的边权应该总可以互不相同地赋上去。
所以答案只需要再 \(n - 1\) 的基础上减去重复的同父叶子即可。
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l); i <= (r); ++ i)
#define G(i,r,l) for(int i(r); i >= (l); -- i)
using namespace std;
using ll = long long;
const int N = 2e5;
vector<int> G[N];
int dis[N], prv[N], siz[N], r1 = 0, r2 = 0;
int n, f1, f2, oo;
string q;
void go(int u, int fa){
dis[u] = dis[fa] + 1;
if(dis[u] > dis[r1]) r1 = u;
for(auto v : G[u]){
if(v == fa) continue;
go(v, u);
}
}
void dfs(int u, int fa){
dis[u] = dis[fa] + 1;
prv[u] = fa;
siz[u] = 1;
if(dis[u] > dis[r2]) r2 = u;
int t = 0;
for(auto v : G[u]){
if(v == fa) continue;
dfs(v , u);
siz[u] += siz[v];
if(siz[v] == 1){
if(t == 1 || fa == r1) -- f2;
t = 1;
}
}
}
signed main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n;
F(i, 1, n - 1){
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
if(n == 3){
cout << "1 1";
return 0;
}
f1 = 1, f2 = n - 1;
go(1, 0);
assert(dis[0] == 0);//////////////////////////
F(i, 0, n) dis[i] = 0;
dfs(r1, 0);
// cout << r1 << ' ' << r2 << ' ' << dis[r2] - dis[r1] << '\n';
F(i, 1, n) if(G[i].size() == 1 && i != r1){
if(f1 == 1 && dis[i] % 2 == 0) f1 = 3;
}
cout << f1 << ' ' << f2 << '\n';
return fflush(0), 0;
}

浙公网安备 33010602011771号