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;
}
posted @ 2025-07-27 15:31  superl61  阅读(15)  评论(0)    收藏  举报