题目:给定一颗无边权的树,你需要对每条边添加任意大于0的数值。对于树上的任意一条链,对链上的所有边进行(xor)操作后数值为0。你最多和最少可以添加不同的边权。
思路:
①最少:我们可以发现,如果任意两个叶子结点间的边为偶数,则我们只需要用"1"就行。如果出现了偶数,则我们只需要用"1","2","3"就可以,我们用"1","2","3"把奇数条变成偶数条(这),然后其他用"1"填充。
②最多:我们可以任意选一个非叶子节点作为根结点,这样就变成了一个有深度的有根树。我们可以知道,一个非叶子节点作为祖先,则它下面的所有边权值(xor)应该都是相同,而且我们可以添加任意的一个数(不限制范围),转为二进制来说,可以是很长的"01"串,这样我们可以有很多组合组成一个相同的数。我们容易知道,如果两个叶子节点距离为2,则他们的权值一定要相同。这样说明除了两个叶子结点距离为2的点,其他点权值都可以不同,然后我们只需要处理一下前面说的特殊情况就行。
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 #include<cstdio> 5 #include <stack> 6 7 #define ll long long 8 #define pb push_back 9 10 using namespace std; 11 12 const int N = 1e5 + 10; 13 vector<int > E[N]; 14 int du[N], deep[N]; 15 struct node 16 { 17 vector<int > son; 18 }info[N]; 19 20 void dfs(int now, int pre) 21 { 22 deep[now] = deep[pre] + 1; 23 for(auto to : E[now]){ 24 if(to == pre) continue; 25 dfs(to, now); 26 } 27 } 28 29 void dfs2(int now, int pre) 30 { 31 for(auto to : E[now]){ 32 if(to == pre) continue; 33 info[now].son.pb(to); 34 dfs2(to, now); 35 } 36 } 37 38 void solve() 39 { 40 int n; 41 cin >> n; 42 43 int u, v; 44 for(int i = 1; i < n; ++i){ 45 cin >> u >> v; 46 E[u].pb(v); 47 E[v].pb(u); 48 du[u]++; 49 du[v]++; 50 } 51 52 int s = -1; 53 for(int i = 1; i <= n; ++i){ 54 if(du[i] > 1) continue; 55 s = i; 56 break; 57 } 58 deep[0] = -1; 59 dfs(s, 0); 60 bool even = 1; 61 for(int i = 1; i <= n; ++i){ 62 if(du[i] > 1) continue; 63 if(du[i] == 1 && deep[i] % 2 == 0) continue; 64 even = 0; 65 break; 66 } 67 for(int i = 1; i <= n; ++i){ 68 if(du[i] == 1) continue; 69 s = i; 70 break; 71 } 72 73 dfs2(s, 0); 74 75 76 int cnt, sum; 77 cnt = 0; 78 for(int i = 1; i <= n; ++i){ 79 if(du[i] == 1) continue; 80 81 if(info[i].son.size() < 2) continue; 82 83 sum = 0; 84 for(auto he : info[i].son){ 85 if(info[he].son.size()) continue; 86 sum++; 87 } 88 if(sum > 0) cnt += sum - 1; 89 } 90 //cout << "ans = "; 91 cout << (even == 1 ? 1 : 3) << " " << n - 1 - cnt << endl; 92 } 93 94 int main() { 95 96 ios::sync_with_stdio(false); 97 cin.tie(0); 98 cout.tie(0); 99 solve(); 100 //cout << "ok" << endl; 101 return 0; 102 }