zoukankan      html  css  js  c++  java
  • NOIp 2018 赛道修建

    题意

    对于一颗有边权的无根树,用(m)条不相交的路径对其进行覆盖(不一定要将整棵树全部覆盖)

    一条路径的权值定义为组成这条路径的边的权值和

    使这(m)条路径中的最小路径的权值最大并输出这个最大值

    (Nleq 5 imes10^4,mleq n-1)


    解法

    这题与巫师的旅行(之前博客里有写)的思路很像!

    先二分答案,再在树上进行覆盖

    同样也是在父亲结点上完成对儿子的两两匹配

    对于需要折一下的路径,是通过两两匹配完成的

    对于路径,判断自底向上链的权值和直接选取即可

    还有一个贪心,为了使树上得到的路径最多,每次对儿子进行匹配的时候,尽量选择两个较小的边两两配对

    具体的实现用(multiset)很方便

    注意,在对一个(set)进行的操作中有删除操作时,最好用(while)遍历整个(set)避免玄学错误


    代码

    #include <cstdio>
    #include <set>
    
    using namespace std;
    
    const int N = 1e5 + 10;
    
    int n, m;
    int f[N];
    
    int link, max1, max2;
    
    int cap;
    int head[N], to[N], nxt[N], val[N];
    
    multiset<int> st[N];
    
    inline void add(int x, int y, int z) {
    	to[++cap] = y, nxt[cap] = head[x], head[x] = cap, val[cap] = z;	
    }
    
    int DFS(int x, int fa, int w) {
    	int res = 0; f[x] = 0;
    	for (int i = head[x]; i; i = nxt[i]) {
    		if (to[i] == fa)	continue;
    		res += DFS(to[i], x, w);
    		int d = f[to[i]] + val[i];
    		if (d >= w)	
    			++res;
    		else
    			st[x].insert(d);
    	}
    	while (!st[x].empty()) {
    		multiset<int> :: iterator it, en;
    		it = st[x].begin();
    		en = st[x].lower_bound(w - (*it));
    		while (it == en && en != st[x].end())	++en;
    		if (en == st[x].end())
    			f[x] = max(f[x], (*it));
    		else 	
    			st[x].erase(en), ++res;
    		st[x].erase(it);
    	}
    	return res;
    }
    
    int main() {
    	
    	scanf("%d%d", &n, &m);
    	
    	int u, v, w;
    	for (int i = 1; i < n; ++i) {
    		scanf("%d%d%d", &u, &v, &w);
    		add(u, v, w), add(v, u, w);
    		if (u != 1)	link = 1;
    		if (w > max1)	
    			max2 = max1, max1 = w;
    		else if (w > max2)
    			max2 = w;
    	}
    	
    	int l = 1, r = link ? (int)1e8 : (max1 + max2), res = 0;
    	while (l <= r) {
    		int mid = l + r >> 1;
    		if (DFS(1, 0, mid) >= m)	
    			l = mid + 1, res = mid;
    		else 
    			r = mid - 1;	
    	}
    		
    	printf("%d
    ", res);
    																					
    	return 0;
    }
    
  • 相关阅读:
    MaltReport2:通用文档生成引擎
    PostgreSQL 10 如何使用 PgAdmin3
    Stackoverflow 珠玑:C#封装重试指定次数的功能
    C# 6 元组应用 Part 2:C# 也玩模式匹配
    C# 6 元组应用 Part 1:方便的字典工厂方法
    Stackoverflow 珠玑:用于分组的 LINQ 扩展方法
    Linux 下的 PostgreSQL 数据库+文件通用自动备份脚本
    让 Odoo POS 支持廉价小票打印机
    NopCommerce 根据手机浏览器和桌面浏览器切换 Theme
    为什么 C# 比 C++ 编译快那么多
  • 原文地址:https://www.cnblogs.com/VeniVidiVici/p/11455729.html
Copyright © 2011-2022 走看看