codeforces 1338 B. Edge Weight Assignment

题意: 给出一棵树,可以给边加任意权值,使任意两叶子之间通路的边权异或和为0,问最少和最多的边权的种类数

思路: 有点猜的,觉得最小的情况要不是1要不是3,1的情况是任意两叶子通路均为偶数个边,其余都是3

最大的情况是看每个叶子到树干的分叉的那个长度如果是1,就把这个节点打个标记,有多个长度为1的分叉在同一个点就只能算一次,(如果长度超过1必可以有不重复的组合出来,
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
vector<int> g[N];
int n;

int solveMax() {
    
    
	vector<int> q;
	q.clear();
	
	for(int i = 1; i <= n; ++ i) {
    
    
		if(g[i].size() == 1) {
    
    
			q.push_back(i);
		}
	}
	
	set<int> se;
	se.clear();
	int tot = 0;
	
	int siz = q.size();
	for(int i = 0; i < siz; ++ i) {
    
    
		int p = q[i];
		int nxt = g[p][0];
		
		if(g[nxt].size() > 2) {
    
    
			se.insert(nxt);
			tot ++;
		}
	}
	
	return n - 1 - tot + se.size();
}

int solveMin() {
    
    
	vector<int> q;
	q.clear();
	
	for(int i = 1; i <= n; ++ i) {
    
    
		if(g[i].size() == 1) {
    
    
			q.push_back(i);
		}
	}
	
	int s = q[0];
	
	queue<int> que;
	while(!que.empty()) que.pop();
	
	bool vis[N] = {
    
    0};
	int dep[n] = {
    
    0};
	
	que.push(s);
	dep[s] = 0;
	
	while(!que.empty()) {
    
    
		int tmp = que.front();
		que.pop();
		
		int siz = g[tmp].size();
		for(int i = 0; i < siz; ++ i) {
    
    
			int u = g[tmp][i];
			if(vis[u]) continue;
			vis[u] = 1;
			
			dep[u] = dep[tmp] + 1;
			
			que.push(u);
		}
	} 
	
	bool flag = 0;
	int siz = q.size();
	for(int i = 0; i < siz; ++ i) {
    
    
		if(dep[q[i]] & 1) flag = 1;
	}
	
	if(flag) {
    
    
		return 3;
	}
	return 1;
} 

int main() {
    
    
	cin >> n;
	for(int i = 0, u, v; i < n - 1; ++ i) {
    
    
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	
	int x = solveMin();
	int y = solveMax();
	if(y == 2) y = 1; 
	
	cout << x << " " << y;
	
	return 0;
}

ps 刚开始错了一个只有2个点的情况,这时候的最大值只有1,要特判一下,(要不是cf能直接看数据点也不知道会卡到什么时候((啊啊啊

猜你喜欢

转载自blog.csdn.net/qq_39602052/article/details/113115717
今日推荐