Codefoeces 1339D Edge Weight Assignment(补)
题意:给定n个点,n-1条没有分配边权的边,要求对于任意两个叶子节点,简单路径的边权异或和为0,定义f为边权的集合
问题一:最小的边权为多少
问题二:求f得最大值
思路:对与问题一有两个点得简单路径异或和为两个点分别到根节点的异或和的疑惑和,即答案只能为1或者3,判断叶子节点的奇偶数就可以有疑问的可以动手画一画。
对于问题二(蒟蒻的我不会,后面看题解也说是猜的结论)如果好多叶子连到一个结点上,这些边的边权被迫相等,只要减去即可,另外,如果把度为1的结点当作根,由于这个结点本来就是叶子,还需要特判,反之就不需要特判,选取一个度为1的点dfs即可。参考https://www.cnblogs.com/axiomofchoice/p/12688806.html侵权删。
code:
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 const int maxn = 2e5 + 10; 5 int n, dep[maxn], indeg[maxn], num[maxn]; 6 int rt, ans, flag = 1; 7 vector<int> vec[maxn]; 8 9 void dfs(int v, int u){ 10 for(int i = 0; i < vec[v].size(); i++){ 11 if(vec[v][i] != u){ 12 dep[vec[v][i]] = dep[v] + 1; 13 dfs(vec[v][i], v); 14 num[v] += (indeg[vec[v][i]] == 1); 15 } 16 } 17 if(indeg[v] == 1 && dep[v] & 1) flag = 0; 18 if(dep[v] == 1) ans -= num[v]; 19 else ans -= max(num[v]-1,0); 20 } 21 22 int main(){ 23 cin>>n; 24 for(int i = 1; i < n; i++){ 25 int x, y; 26 cin>>x>>y; 27 indeg[x]++, indeg[y]++; 28 vec[x].push_back(y), vec[y].push_back(x); 29 } 30 for(int i = 1; i <= n; i++) if(indeg[i] == 1){rt = i;break;} 31 dfs(rt, 0); 32 ans += n - 1; 33 if(flag) cout<<1<<" "<<ans<<endl; 34 else cout<<3<<" "<<ans<<endl; 35 return 0; 36 }

浙公网安备 33010602011771号