显然两步之内决胜负。否则两个人会来回拉扯,平局。
考虑何时 Aron 会赢。
称与叶子结点边距离小于等于 \(1\) 的结点为【制胜点】。
- 开局 \(q\) 在叶子,\(p\) 不在叶子,直接赢。方案数 \(c(n-c)\),其中 \(c\) 为叶子数量。
- \(q\) 在一个连着【制胜点】的点,\(p\) 不在【制胜点】。Nora 被迫把 \(q\) 移到【制胜点】,随后 Aron 赢。
针对第二种情况,我们考虑树形 DP。对于可能的 \(q\):
- \(p\) 在子树内:我们枚举 \(q\) 的儿子 \(v\),如果其为【制胜点】,则答案加上 \(v\) 子树内的非【制胜点】个数(安放 \(p\))。
- \(p\) 在子树外:此时 \(q\) 的父亲必须为【制胜点】。答案加上 \(q\) 子树外的非【制胜点】个数即可。
做完了,时间复杂度 \(O(n)\)。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define Linf 0x3f3f3f3f3f3f3f3f
#define pii pair<int, int>
#define all(v) v.begin(), v.end()
using namespace std;
//#define filename "xxx"
#define FileOperations() freopen(filename".in", "r", stdin), freopen(filename".out", "w", stdout)
namespace Traveller {
const int N = 2e5+2;
int n;
vector<int> g[N];
int leaf[N], sp[N], par[N];
int sum[N], sz[N];
void DFS(int u, int fa) {
par[u] = fa;
sum[u] = sp[u];
sz[u] = 1;
for(auto v : g[u]) {
if(v == fa) continue;
DFS(v, u);
sum[u] += sum[v];
sz[u] += sz[v];
}
}
bool check(int u) {
if(leaf[u]) return false;
for(auto v : g[u])
if(!sp[v]) return false;
return true;
}
void main() {
cin >> n;
for(int i = 1; i <= n; ++i) vector<int>().swap(g[i]);
for(int i = 1, u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
g[u].push_back(v), g[v].push_back(u);
}
if(n == 2) {
puts("0");
return;
}
int cnt = 0;
for(int i = 1; i <= n; ++i)
if((int)g[i].size() == 1) ++cnt;
long long ans = 1ll * cnt * (n - cnt);
int root = 1;
for(int i = 1; i <= n; ++i)
if((int)g[i].size() > 1) {
root = i;
break;
}
memset(sum, 0, sizeof(int) * (n+1));
memset(sz, 0, sizeof(int) * (n+1));
memset(leaf, 0, sizeof(int) * (n+1));
memset(sp, 0, sizeof(int) * (n+1));
for(int i = 1; i <= n; ++i)
if((int)g[i].size() == 1) {
leaf[i] = sp[i] = 1;
for(auto v : g[i]) sp[v] = 1;
}
DFS(root, 0);
for(int i = 1; i <= n; ++i) {
if(leaf[i]) continue;
if(i != root && sp[par[i]] && !leaf[par[i]]) ans += (n - sz[i]) - (sum[root] - sum[i]);
for(auto v : g[i]) {
if(v == par[i]) continue;
if(sp[v] && !leaf[v]) ans += sz[v] - sum[v];
}
}
printf("%lld\n", ans);
}
}
signed main() {
#ifdef filename
FileOperations();
#endif
int _;
cin >> _;
while(_--) Traveller::main();
return 0;
}
标签:sz,return,int,题解,sum,CF2053E,Caterpillar,制胜,define
From: https://www.cnblogs.com/wfc284/p/18652338