[ABC394F] Alkane
[ABC394F] Alkane
思路
先忽略至少存在一个度数为 \(4\) 的顶点的限制,当忽略限制后得到的最大答案为 \(1\) 时,该树无解。
从任意一个未被访问过的点开始 dfs,对每个点统计该点的子树能贡献的最大值以及能对父亲节点贡献的最大值,设点 \(i\) 对父亲贡献的值为 \(w_i\)。对于每个点 \(i\) 进行如下考虑:
- 点 \(i\) 的儿子数量 \(<3\)。
不能从该点继续往下扩展,此时该点答案为 \(1\),\(w_i=1\)。
- 该点的儿子数量 \(=3\)。
此时该点答案为 \(1\)(因为这棵子树内该点度数小于 \(4\)),但是能对父亲节点产生贡献(因为包含父亲节点后度数等于 \(4\)),设该点的儿子分别为 \(v_1,v_2,v_3\),则 \(w_i=w_{v_1}+w_{v_2}+w_{v_3}+1\)。
- 该点的儿子数量 \(\ge 4\)。
设 \(w\) 中前 \(4\) 大的点分别为 \(v_1,v_2,v_3,v_4\),则该点答案为 \(w_{v_1}+w_{v_2}+w_{v_3}+w_{v_4}+1\),对父亲的贡献 \(w_i=w_{v_1}+w_{v_2}+w_{v_3}+1\)。
最终答案即为每个点对答案贡献的最大值。
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n,ans;
vector<int> t[200005];
bool vis[200005];
int dfs(int x,int fa){
vis[x]=true;
if(t[x].size()<4) return 1;
multiset<int> mx;
for(int v:t[x]){
if(v!=fa){
mx.insert(dfs(v,x));
if(mx.size()>=5) mx.erase(mx.begin());
}
}
int tot=0;
for(int v:mx)
tot+=v;
if(mx.size()==4){
ans=max(ans,tot);
return tot+1-*mx.begin();
}
else return tot+1;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>n;
for(int x,y,i=1;i<n;i++){
cin>>x>>y;
t[x].push_back(y);
t[y].push_back(x);
}
for(int i=1;i<=n;i++)
if(!vis[i])
dfs(i,0);
cout<<(ans==0?-1:ans+1);
return 0;
}

浙公网安备 33010602011771号