zoukankan      html  css  js  c++  java
  • [USACO 2011 Dec Gold] Cow Calisthenics【二分】

    Problem 1: Cow Calisthenics [Michael Cohen, 2010]
    
    Farmer John continues his never-ending quest to keep the cows fit
    by having them exercise on various cow paths that run through the
    pastures. These cow paths can be represented as a set of vertices
    connected with bidirectional edges so that each pair of vertices
    has exactly one simple path between them. In the abstract, their
    layout bears a remarkable resemblance to a tree. Surprisingly, each
    edge (as it winds its way through the pastures) has the same length.
    
    For any given set of cow paths, the canny cows calculate the longest
    possible distance between any pair of vertices on the set of cowpaths
    and call it the pathlength. If they think this pathlength is too
    large, they simply refuse to exercise at all.
    
    Farmer John has mapped the paths and found V (2 <= V <= 100,000)
    vertices, conveniently numbered from 1..V. In order to make shorter
    cowpaths, he can block the path between any two vertices, thus
    creating more sets of cow paths while reducing the pathlength of
    both cowpath sets.
    
    Starting from a single completely connected set of paths (which
    have the properties of a tree), FJ can block S (1 <= S <= V-1)
    paths, creating S+1 sets of paths. Your goal is to compute the best
    paths he can create so that the largest pathlength of all those
    sets is minimized.
    
    Farmer John has a list of all V-1 edges in his tree, each described
    by the two vertices A_i (1 <= A_i <= V) and B_i (1 <= B_i <= V; A_i
    != B_i) that it connects.
    
    Consider this rather linear cowpath set (a tree with 7 vertices):
    
                       1---2---3---4---5---6---7
    
    If FJ can block two paths, he might choose them to make a map like
    this:
    		   1---2 | 3---4 | 5---6---7
    
    where the longest pathlength is 2, which would be the answer in
    this case. He can do no better than this.
    
    TIME LIMIT: 2 seconds
    
    MEMORY LIMIT: 32 MB
    
    PROBLEM NAME: exercise
    
    INPUT FORMAT:
    
    * Line 1: Two space separated integers: V and S
    
    * Lines 2..V: Two space separated integers: A_i and B_i
    
    SAMPLE INPUT (file exercise.in):
    
    7 2
    6 7
    3 4
    6 5
    1 2
    3 2
    4 5
    
    OUTPUT FORMAT:
    
    * Line 1: A single integer that is the best maximum pathlength FJ can
            achieve with S blocks
    
    SAMPLE OUTPUT (file exercise.out):
    
    2
    

    不懂英文自行解决。。。

    一看到最大值最小,就是二分,可是想了半天也没想出来如何check。看了题解,恍然大悟。

    随便选一个根拉成一棵树,然后对于以r为根的子树,假设以其儿子节点为根的子树中该断的边已经断了,那么对于以r为根的子树中,其直径为“最深”的两个儿子i与j的深度之和 + 2,“最深”的意思是,以这两个节点往下走能走的最深。如果这个值大于二分的那个最大值,则最深的那个儿子就要断开与r的连接,这样直到“最深”的两个儿子i与j的深度之和 + 2 <= 二分的最大值。当有一个节点时同理,反正剩下就是细节了。

    #include <cstdio>
    #include <vector>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    
    const int maxn = 100005;
    
    int n, s, t1, t2, ans_s, root, biaozhun;
    int head[maxn], to[maxn << 1], next[maxn << 1], lb;
    std::vector<int> son[maxn];
    
    inline void ist(int aa, int ss) {
    	to[lb] = ss;
    	next[lb] = head[aa];
    	head[aa] = lb;
    	++lb;
    }
    bool cmp(int aa, int ss) {
    	return aa > ss;
    }
    int dfs(int r, int p) {
    	for (int j = head[r]; j != -1; j = next[j]) {
    		if (to[j] != p) {
    			son[r].push_back(dfs(to[j], r));
    		}
    	}
    	std::sort(son[r].begin(), son[r].end(), cmp);
    	if (son[r].size() > 1) {
    		int lmt = son[r].size();
    		int i;
    		for (i = 0; i < lmt - 1; ++i) {
    			if (son[r][i] + son[r][i + 1] + 2 <= biaozhun) {
    				break;
    			}
    			++ans_s;
    		}
    		if (i == lmt - 1) {
    			if (son[r][i] + 1 > biaozhun) {
    				++ans_s;
    				return 0;
    			}
    			else {
    				return son[r][i] + 1;
    			}
    		}
    		else {
    			return son[r][i] + 1;
    		}
    	}
    	else if (son[r].size() == 1) {
    		if (son[r][0] + 1 > biaozhun) {
    			++ans_s;
    			return 0;
    		}
    		else {
    			return son[r][0] + 1;
    		}
    	}
    	else {
    		return 0;
    	}
    }
    inline bool check(int mx) {
    	ans_s = 0;
    	biaozhun = mx;
    	for (int i = 1; i <= n; ++i) {
    		son[i].clear();
    	}
    	dfs(root, 0);
    	return ans_s <= s;
    }
    
    int main(void) {
    	freopen("exercise.in", "r", stdin);
    	freopen("exercise.out", "w", stdout);
    	memset(head, -1, sizeof head);
    	memset(next, -1, sizeof next);
    	unsigned seed;
    	scanf("%d%d", &n, &s);
    	seed += n + s;
    	for (int i = 1; i < n; ++i) {
    		scanf("%d%d", &t1, &t2);
    		seed += t1 + t2;
    		ist(t1, t2);
    		ist(t2, t1);
    	}
    	srand(seed);
    	root = rand() % n + 1;
    	
    	int left = 0, right = n, mid;
    	while (left != right) {
    		mid = (left + right) >> 1;
    		if (check(mid)) {
    			right = mid;
    		}
    		else {
    			left = mid + 1;
    		}
    	}
    	printf("%d
    ", left);
    	return 0;
    }
    

      

  • 相关阅读:
    C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现之方法二:加入缓存机制
    如何将CKeditor编辑器的上传和thinkphp结合
    在 VisualStudio 给文件起一个带分号的文件名会怎样
    dotnet ConditionalWeakTable 的底层原理
    GitHub 的 Action 判断仅在主仓库才执行脚本
    ASP.NET Core 将文件夹内容输出为压缩包文件方法
    dotnet Microsoft.Recognizers.Text 超强大的自然语言关键词提取库
    dotnet CBB 为什么决定推送 Tag 才能打包
    WPF 通过 InputManager 模拟调度触摸事件
    如何参与 .NET 的开发和设计
  • 原文地址:https://www.cnblogs.com/ciao-sora/p/6040370.html
Copyright © 2011-2022 走看看