Wunder Fund Round 2016 D. Hamiltonian Spanning Tree(贪心+dp)★ ★ ★
2016-08-26 19:49
351 查看
转载自:http://blog.csdn.net/lwt36/article/details/50614467
题意:
N≤2×105个点的完全图,边权为y
现给定其中N−1条边,改变其权值为x,保证这个N−1条边形成树
试求出一条任意起点权值最小的哈密顿路
分析:
首先对于x>y的情况,我们总有可以走不是树边的办法,除了星形图必须要走一条树边
构造如下:
首先树是一个二分图,找到2个点x∈X,y∈Y,且x,y没有边相连
我们知道二分图X部内,Y部内是没有边的,只要把X部走一圈然后停在x,走到y,然后把Y部走一圈就好了
但是当|X|=1或者|Y|=1时找不到这样的x,y,也就是星形图特判一下就好了,其他时候总可以这样找到
对于x≤y的情况,我们显然是要走最多的树边,也就说让树由尽可能少的点不相交的链构成(链之间我们只能走非树边了)
也就是“最小路径覆盖”的感觉
考虑一个贪心,当一个子树有≥2个儿子,只能把2个儿子以及当前根连通过树边起来,其它的儿子只能通过非树边来连接了,并且这颗子树不能再被其父亲通过树边相连
如果只有1个儿子就可以向根连树边,且当前这颗子树可以继续被它的父亲通过树边相连
这样自底向上贪心即可,证明就只能坐等CF出题人的证明了
题意:
N≤2×105个点的完全图,边权为y
现给定其中N−1条边,改变其权值为x,保证这个N−1条边形成树
试求出一条任意起点权值最小的哈密顿路
分析:
首先对于x>y的情况,我们总有可以走不是树边的办法,除了星形图必须要走一条树边
构造如下:
首先树是一个二分图,找到2个点x∈X,y∈Y,且x,y没有边相连
我们知道二分图X部内,Y部内是没有边的,只要把X部走一圈然后停在x,走到y,然后把Y部走一圈就好了
但是当|X|=1或者|Y|=1时找不到这样的x,y,也就是星形图特判一下就好了,其他时候总可以这样找到
对于x≤y的情况,我们显然是要走最多的树边,也就说让树由尽可能少的点不相交的链构成(链之间我们只能走非树边了)
也就是“最小路径覆盖”的感觉
考虑一个贪心,当一个子树有≥2个儿子,只能把2个儿子以及当前根连通过树边起来,其它的儿子只能通过非树边来连接了,并且这颗子树不能再被其父亲通过树边相连
如果只有1个儿子就可以向根连树边,且当前这颗子树可以继续被它的父亲通过树边相连
这样自底向上贪心即可,证明就只能坐等CF出题人的证明了
#include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; #define pr(x) cout << #x << " = " << x << " " #define prln(x) cout << #x << " = " << x << endl const int N = 2e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7; int n, x, y; vector<int> G ; bool available ; void dfs(int u, int f, int &tree) { int cnt = 0; for(int v : G[u]) { if(v == f) continue; dfs(v, u, tree); cnt += available[v]; } available[u] = cnt < 2; tree += min(cnt, 2); } int main() { #ifdef LOCAL freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin); // freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); while(scanf("%d%d%d", &n, &x, &y) == 3) { for(int i = 1; i <= n; ++i) G[i].clear(); for(int i = 1; i < n; ++i) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } if(x < y) { int tree = 0; memset(available, false, sizeof available); dfs(1, -1, tree); long long ans = 1LL * tree * x + 1LL * (n - 1 - tree) * y; printf("%I64d\n", ans); } else { bool star = false; for(int i = 1; i <= n; ++i) star |= G[i].size() == n - 1; long long ans = 1LL * (n - 2) * y + (star ? x : y); printf("%I64d\n", ans); } } return 0; }
相关文章推荐
- Wunder Fund Round 2016 D. Hamiltonian Spanning Tree(贪心+dp)
- 【Wunder Fund Round 2016 (Div 1 + Div 2 combined)D】【贪心 dfs】Hamiltonian Spanning Tree 树的最小链划分
- Wunder Fund Round 2016 D. Hamiltonian Spanning Tree
- 【Wunder Fund Round 2016 (Div 1 + Div 2 combined)B】【暴力 贪心】Guess the Permutation 全排列a[i][j]=min(p[i],p
- Wunder Fund Round 2016 C. Constellation(贪心+计算几何)
- CF618D:Hamiltonian Spanning Tree(贪心 & 树形dp & 最小路径覆盖)
- Codeforces 618 D Hamiltonian Spanning Tree 贪心+dp
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined)-C. Constellation(贪心+向量平行判断)
- Wunder Fund Round 2016 C. Constellation(贪心+计算几何)
- 【Wunder Fund Round 2016 (Div 1 + Div 2 combined)A】【二进制拆分】Slime Combining 特殊规则二进制拆分
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) CF618A A. Slime Combining
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined)
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) ---补题
- cf#Wunder Fund Round 2016 -A - Slime Combining-简单数学
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined)(A)(模拟||规律)
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) A. Slime Combining 水题
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined)(B)(构造,找规律)
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) B. Guess the Permutation 水题
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) C. Constellation
- 【Wunder Fund Round 2016 (Div 1 + Div 2 combined)C】【排序 共线判定】平面n点不共一线,寻找不含点的任一三角形