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;
    }
    
  • 相关阅读:
    Netty之WebSocket和四种IO介绍
    java递归展示树形图代码实现以及遇到的问题
    String、String Buffer、String Builder
    物联网的开发应该是什么样子?
    最新 去掉 Chrome 新标签页的8个缩略图
    复化梯形求积分——用Python进行数值计算
    每日设置Bing首页图片为壁纸
    分段二次插值——用Python进行数值计算
    埃尔米特插值问题——用Python进行数值计算
    牛顿插值法——用Python进行数值计算
  • 原文地址:https://www.cnblogs.com/VeniVidiVici/p/11455729.html
Copyright © 2011-2022 走看看