USACO2020DEC第四题(Cowntagion)题解

题目
题目描述
Farmer John 和他的农民团队为了控制牛传染病 COWVID-19 在他们农场间的传播而夜以继日地工作。
他们共同监控着 NN 个农场(1≤N≤10^5 ),编号为 1…N。农场间由 N−1条道路连接,使得每个农场都可以从农场 1出发经过一些道路到达。
很不幸,农场 1中的一头奶牛的 COWVID-19 检测呈阳性。暂时这个农场的其他奶牛以及其他农场的所有奶牛都还没有染上疾病。然而,根据这个疾病通过接触传播的特性,Farmer John 推测每一天都会有以下不利的事件之一发生:
(1) 在一个农场内,「超级传播者」导致该农场感染 COWVID-19 的奶牛数量翻倍;或者
(2) 一头感染 COWVID-19 的奶牛从一个农场沿道路去往了一个相邻的农场。
Farmer John 担心疫情会很快爆发。请帮助 Farmer John 求出每个农场内均有至少一头奶牛感染疾病所需经过的最小天数。
输入格式
输入的第一行包含一个整数 N。以下 N−1行每行包含两个空格分隔的整数 a 和 b,表示一条农场 a 与 b之间的道路。a和 b均在 1…N 范围内。
输出格式
输出疫情爆发至所有农场所需经过的最小天数。
输入输出样例
输入
4
1 2
1 3
1 4
输出
5
说明/提示
该样例对应的一个可能的事件序列如下:农场 1 内染病的奶牛数量翻倍再翻倍,使得两天后农场 1 内有 4 头染病的奶牛。在此后 3 天,分别有一头染病的奶牛从农场 1 去往农场 2、3 和 4。5 天过后每个农场均有至少 1 头染病的奶牛。
测试点 1-4 中,每个农场均直接与农场 1 相连(除农场 1 外)。
测试点 5-7 中,农场 2…N均至多与两条道路相连。
测试点 8-15 没有额外限制。
解题思路
显然,我们可以将a[u]不停地乘2,知道a[u]>son[u](son[u]表示u的子节点个数),然后将a[u]减去son[u],将u的每一个儿子v的a[v]都变成1。乘2的效率肯定比加1要高,所以我们可以采用这种方法。
参考代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
struct node {
    
    
	int to, nxt;
    node(int to = 0, int nxt = 0): to(to), nxt(nxt) {
    
    }
} e[N * 2];
int n, tot, ans, son[N], fa[N], cnt[N], head[N];
void add(int u, int v) {
    
    
	e[++tot] = node(v, head[u]); head[u] = tot;
}
void dfs(int u) {
    
    
	cnt[u] = 1;
	for (int i = head[u]; i; i = e[i].nxt) {
    
    
		int v = e[i].to;
        if (v == fa[u]) {
    
    
            continue;
        }
		fa[v] = u; dfs(v); ++cnt[u];
	}
}
void bfs() {
    
    
	queue<int> q; q.push(1);
	while (q.size()) {
    
    
		int u = q.front(); q.pop(); ans += son[cnt[u]];
		for (int i = head[u]; i; i = e[i].nxt) {
    
    
			int v = e[i].to;
            if (v == fa[u]) {
    
    
                continue;
            }
			q.push(v);
		}
	}
}
int main() {
    
    
	cin >> n; ans = n - 1;
	for (int i = 2; i <= n; ++i) {
    
    
        son[i] = son[i >> 1] + 1;
    }
	for (int i = 2; i <= n; ++i) {
    
    
        if (i & (i - 1)) {
    
    
            ++son[i];
        }
    }
	for (int i = 1; i < n; ++i) {
    
    
		int u, v; cin >> u >> v;
		add(u, v); add(v, u);
	}
	dfs(1); bfs();
	cout << ans << '\n';
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yueyuedog/article/details/112425783
今日推荐