洛谷P8552 Rabbit

83 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
本文已参与「新人创作礼」活动,一 起开启掘金创作之路。
题目链接
题目

屏幕截图 2022-10-06 214303.png 题目分析
就是让我们去找一个树状结构如下图

image.png
只需要中间节点的值大于两侧节点那么是肯定可以操作一次的
所以我们以大结点向小节点连边

image.png
所以我们只需遍历这个节点与之两边的点看是否有超过两个长度大于一的点在此过程中我们用并查集去维护与此点相连并且小于该点的个数即可
Code

vector<int> v[N];
int f[N];
int siz[N];
int find(int x) { return f[x] == x ? f[x] : f[x] = find(f[x]);}
void solve()
{
   int n; cin >> n;
   rep(i,n) v[i].clear();
   rep(i,n) f[i] = i,siz[i] = 1;
   int res = 0;
   rep(i,n - 1) {
     int x,y; cin >> x >> y;
     v[max(x,y)].pb(min(x,y));
   }
   rep(i,n) {
     int cnt = 0;
     for(auto u : v[i]) {
        int fa = find(i);
        int fb = find(x);
        if(siz[fb] >= 1) cnt ++;
        siz[fa] += siz[fb];
        f[find(x)] = fa;
     }
     if(cnt >= 2) res ++,siz[find(i)] -= 3;
   }
   cout << res << endl;
}