专栏文章
[CF2063C] Remove Exactly Two 题解
CF2063C题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @miqf4k46
- 此快照首次捕获于
- 2025/12/04 03:46 3 个月前
- 此快照最后确认于
- 2025/12/04 03:46 3 个月前
前言
CF 好题。
正文
题意:有一个无根树,移除 点之后联通分量的个数最大是多少。
以下皆钦定度数为入度和出度的和。
设节点 的度数为 ,我们对依次移除的 点 进行分类讨论。
-
若 不相邻:断开 点,树显然会变成有 个连通分量的图。断开 点,会再多出 个联通分量。为什么呢?因为在刚刚断开的 个分量里面必有 个包含 (也包含其他的节点),断开 不会影响这一个连通分量,因此会少多出来 个连通分量。答案为 。
-
若 相邻:与 (1) 同样的逻辑,断开 点,树还是会变成有 个连通分量的图。但是,断开 点,我们会比刚刚再少多出来一个连通分量,因为移除 点的同时 点的度数也 了。答案为 。
问题来了,那怎么实现呢?
具体的,我们枚举点 ,然后根据上面的找出最大的满足条件的点 。
注意到我们需要一个能实时排序,插入和移除的数据结构,我这里用的是
std::set 和 std::multiset。具体实现细节看代码。
Code
时间复杂度显然为 。
CPP#include <bits/stdc++.h>
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) 42
#endif
#define mkp make_pair
#define pb emplace_back
#define endl "\n"
using namespace std;
using ll = long long;
int n,m,t,cnt=0;
const int maxn=2e5+10;
const double eps=1e-6;
int deg[maxn];
vector<int> e[maxn];
void solve(){
int ans=0;
cin>>n;
fill(deg+1,deg+1+n,0);
for(int i=1;i<=n;i++) e[i].clear();
for(int i=1;i<=n-1;i++){
int u,v;cin>>u>>v;
deg[u]++,deg[v]++;
e[u].pb(v);
e[v].pb(u);
}
set<pair<int,int>> st;
for(int i=1;i<=n;i++) st.insert(mkp(deg[i],i));
for(int i=1;i<=n;i++){
multiset<int> mt;
st.erase(mkp(deg[i],i));
for(int v:e[i]){mt.insert(deg[v]);st.erase(mkp(deg[v],v));}
int case2=deg[i]+*prev(mt.end())-2;
if(st.size()){
int case1=deg[i]+(*prev(st.end())).first-1;
ans=max({ans,case1,case2});
}else{ans=max({ans,case2});}
st.insert(mkp(deg[i],i));
for(int v:e[i]) st.insert(mkp(deg[v],v));
}
cout<<ans<<endl;
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(0);
cin>>t;
while(t--) solve();
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...