CF 1338B Edge Weight Assignment

传送门

题目:给定一颗无边权的树,你需要对每条边添加任意大于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 }

 

posted @ 2020-08-21 20:00  SummerMingQAQ  阅读(140)  评论(0编辑  收藏  举报