题目:点击打开链接
题意:n个点的无向完全图,所有边权都是y,给出一个生成树,并把生成树上的n-1条边边权改为x,求这个图的最小边权和的欧拉通路,只输出最小边权和
x > y 时应尽量使用生成树上的边,每个点只能经过一次,相当于一个链状结构,问题等于去掉最少的边使得树变成多条链
然后就不会了55555
看了题解才会,太强了,短短10行代码。。。。。
贪心策略:每个点都尽可能的和子节点构成链状结构,从最底层叶子节点向上判断,因为我的父节点并不能很好的抉择和哪一个子节点构成链状结构,因此先解决子节点,如果子节点和子节点的子节点构成了一条不能和父节点连通的链,那就不选择这个子节点,从而可以选择其他还没有饱和的子节点。
x < y 时应尽量使用不在生成树上的边,当存在一个点,和其他点都直接连接时,这时不得不选择一个树上的点,
其余都可以找到一个条所有边都不在树上的欧拉通路
#include<bits/stdc++.h>
using namespace std;
int index, book[200005], use;
vector<int> w[200005];
int dfs(int fa, int x){
int left = 2;
for(int i = 0; i < w[x].size(); i++){
if(w[x][i] == fa)
continue;
if(dfs(x, w[x][i]) && left){
use++, left--;
}
}
return left;
}
int main(){
int n, u, v;
long long x, y;
cin >> n >> x >> y;
for(int i = 1; i < n; i++){
scanf("%d %d", &u, &v);
w[u].push_back(v);
w[v].push_back(u);
book[u]++, book[v]++;
}
if(x <= y){
dfs(0, 1);
cout << use * x + (n - 1 - use) * y << endl;
}
else{
int flag = 0;
for(int i = 1; i <= n; i++){
if(book[i] == n - 1)
flag = 1;
}
cout << y * (n - 1 - flag) + flag * x << endl;
}
}