CF1338 B. Edge Weight Assignment

CF1338 B. Edge Weight Assignment

題意

一棵n個結點的樹,求最小和最大須要多少個不一樣的路徑來構造樹的路徑權值,使得任意兩片葉子的路徑異或和爲0。html

思路

首先這是一棵無根樹,以其任意一個葉子結點爲根。(避免討論)
首先考慮最小,最小要麼爲1要麼爲3。
爲1的狀況是任意結點到根節點的距離爲偶數。
爲3的狀況是隻要有一個結點到根結點的距離爲奇數。
這裏僅判斷奇偶有兩種寫法,1是記錄深度,2是利用異或。
1^1=0 0^1=1ios

接着考慮最大,咱們發現當一個父節點直接與>1個葉子結點相連,則因爲那些葉子結點到父節點的距離爲1,因此他們的邊權值必定相等,故這些邊視爲同樣的。
f m a x = n 1 f_{max}=n-1-全部直接與同一個父節點相連的葉子結點的數量 c++

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF  = 0x3f3f3f3f;
const ll  mod  = 1e9 + 7;
const ll  maxn = 1e6 + 5;
const int N = 1e5 +5;

ll n,maxf,minf=1,cnt=0,k=0;
vector<int > G[N];
int tot[N];

void dfs(int u,int fa,int d){
	if(G[u].size()==1&&d%2==0) minf=3;
	for(auto c:G[u]){
		if(c==fa) continue;
		dfs(c,u,d+1);
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n;
	for(int i=1;i<n;i++){
		int x,y;cin>>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
	}
	maxf=n-1;
	for(int i=1;i<=n;i++){
		if(G[i].size()==1) tot[G[i][0]]++;
	}
	for(int i=1;i<=n;i++){
		if(tot[i]>1) maxf-=tot[i]-1;
	}
	for(int i=1;i<=n;i++){
		if(G[i].size()==1) {dfs(i,-1,1);break;}
	}
	cout<<minf<<" "<<maxf<<'\n';
	return 0;
}