ABC394F题解

今天我们来讲‌Anti bribe & corruption 394 AtCoder Beginner Contest 394_F。这道题把我干成沙子了。

原题

题目描述

给定一棵包含 N N N 个顶点的无向树 T T T。顶点编号为 1 , 2 , ... , N 1, 2, \ldots, N 1,2,...,N,第 i i i 条边连接顶点 A i A_i Ai 和顶点 B i B_i Bi。

定义满足以下两个条件的图为烷烃

  • 该图是一棵无向树
  • 所有顶点的度数为 1 1 1 或 4 4 4,且至少存在一个度数为 4 4 4 的顶点

请判断 T T T 中是否存在满足烷烃定义的子图。若存在,求此类子图的顶点数的最大值;否则输出 − 1 -1 −1。

输入格式

输入通过标准输入按以下格式给出:

N N N
A 1 A_1 A1 B 1 B_1 B1
A 2 A_2 A2 B 2 B_2 B2
⋮ \vdots ⋮
A N − 1 A_{N-1} AN−1 B N − 1 B_{N-1} BN−1

输出格式

若存在满足烷烃定义的子图,输出其顶点数的最大值;否则输出 − 1 -1 −1。

输入输出样例 #1

输入 #1

9
1 2
2 3
3 4
4 5
2 6
2 7
3 8
3 9

输出 #1

8

输入输出样例 #2

输入 #2

7
1 2
1 3
2 4
2 5
3 6
3 7

输出 #2

-1

输入输出样例 #3

输入 #3

15
8 5
2 9
1 12
6 11
9 3
15 1
7 12
7 13
10 5
6 9
5 1
1 9
4 5
6 14

输出 #3

11

说明/提示

约束条件

  • 1 ≤ N ≤ 2 × 1 0 5 1 \leq N \leq 2 \times 10^5 1≤N≤2×105
  • 1 ≤ A i , B i ≤ N 1 \leq A_i, B_i \leq N 1≤Ai,Bi≤N
  • 输入的图是一棵无向树
  • 所有输入值为整数

样例解释 1

选取顶点 1 , 2 , 3 , 4 , 6 , 7 , 8 , 9 1, 2, 3, 4, 6, 7, 8, 9 1,2,3,4,6,7,8,9 及边 ( 1 , 2 ) (1,2) (1,2)、 ( 2 , 3 ) (2,3) (2,3)、 ( 3 , 4 ) (3,4) (3,4)、 ( 2 , 6 ) (2,6) (2,6)、 ( 2 , 7 ) (2,7) (2,7)、 ( 3 , 8 ) (3,8) (3,8)、 ( 3 , 9 ) (3,9) (3,9) 构成的子图满足烷烃条件。其中顶点 2 2 2 和顶点 3 3 3 的度数为 4 4 4,其余顶点度数为 1 1 1,因此顶点数的最大值为 8 8 8。

翻译由 DeepSeek R1 完成

思路

这道题是一个树形 D P DP DP。

状态

d p u , i dp_{u,i} dpu,i 为以 u u u 为根节点,有 i i i 个子节点,最大节点个数。因为最多只能有四个,所以不会炸。

初始化

d p u , 0 dp_{u,0} dpu,0 是 1 1 1 就是它本身。其它的就为无穷小。

转移方程

d p u , i = m a x ( d p u , i , d p u , i − 1 + m a x ( d p v , 0 , d p v , 3 ) ) dp_{u,i}=max(dp_{u,i},dp_{u,i-1}+max(dp_{v,0},dp_{v,3})) dpu,i=max(dpu,i,dpu,i−1+max(dpv,0,dpv,3))。

也就是说它可以选择加这个儿子或不加。要加的话就必须从儿子有三个或零个子节点中选,不然就不满足要求。由此可以推出此方程

Code

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,h[414514],e[414514],ne[414514],idx,dp[414514][5],mx=-1;
void add(int u,int v){
	e[idx]=v,ne[idx]=h[u],h[u]=idx++;
} 
void dfs(int u,int pre){
	dp[u][1]=-0x3f3f3f3f,dp[u][2]=-0x3f3f3f3f,dp[u][3]=-0x3f3f3f3f,dp[u][4]=-0x3f3f3f3f;
	dp[u][0]=1;
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		if(j==pre){
			continue;
		}
		dfs(j,u);
		for(int i=4;i>=1;i--){
			dp[u][i]=max(dp[u][i],dp[u][i-1]+max(dp[j][0],dp[j][3]));
		}
	}
	if(dp[u][1]>2){
		mx=max(mx,dp[u][1]);
	} 
	mx=max(mx,dp[u][4]);
}
int main(){
	memset(h,-1,sizeof(h));
	cin>>n;
	for(int i=1;i<=n-1;i++){
		int u,v;
		cin>>u>>v;
		add(u,v);
		add(v,u);
	}
	dfs(1,0);
	cout<<mx;
	return 0;
}
相关推荐
灰灰学姐4 小时前
Floyd算法——有向图
数据结构·算法·图论
Rachela_z4 小时前
代码随想录算法训练营第五十七天| 图论03
算法·图论
kill bert13 小时前
代码随想录第五十天| 图论理论基础
java·算法·动态规划·图论
adam_life1 天前
【http://noi.openjudge.cn/】4.3算法之图论——1538:Gopher II
算法·图论·二分图·匈牙利算法·深搜
银河梦想家1 天前
【Day53 LeetCode】图论问题
算法·leetcode·图论
Ritsu栗子1 天前
代码随想录算法训练day67---图论系列11《Floyd 算法&A*算法》
c++·算法·图论
圆圆滚滚小企鹅。1 天前
刷题记录 HOT100 图论-3:207. 课程表
笔记·python·算法·leetcode·深度优先·图论·广度优先
-Michelangelo-1 天前
《代码随想录第五十五天》——图论基础、深度搜索理论基础、所有可达路径、广度搜索理论基础
图论
bee-y1 天前
力扣hot100——图论
leetcode·深度优先·图论