1 条题解
-
0陈烨鑫 (chenyexin) LV 10 @ 2023-4-25 19:59:22
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <vector> using namespace std; /* dp[i][0] 表示i结点为根的子树被覆盖并且 i结点上有塔 dp[i][1] 表示i结点为根的子树被覆盖并且i结点上没有塔 dp[i][2]表示i结点为根的子树除了i全被覆盖了 */ int n , dp[10007][3] ; vector <int> G[10007] ; void dfs(int x , int fa ) { dp[x][0] = 1 ; dp[x][1] = 7777777; int sum = 0 ; int z = G[x].size() ; for(int i = 0 ; i < z ; ++ i ) { int s = G[x][i]; if( s == fa ) continue; dfs( s , x ); dp[x][0] += min( dp[s][0] , min(dp[s][1] , dp[s][2] ) );//可以由这三种情况转移 sum += min( dp[s][0] , dp[s][1] );//进行在 x 节点下的节点全覆盖求和 dp[x][2] += dp[s][1];//要让 x 节点未被覆盖,必须由其子节点的dp[s][1]转移 } if( z == 1 && x!= 1 ) return ; for(int i = 0 ; i < z ; ++ i ) { int s = G[x][i]; if( s == fa ) continue; dp[x][1] = min( dp[x][1] , dp[s][0] + sum - min( dp[s][0] , dp[s][1] ));//该情况由在其子节点建塔dp[s][0]加上其子节点全覆盖的和 减去 之前在该状态下的累加 } } int main() { scanf("%d", &n ); for(int i = 1 ; i < n ; ++ i ) { int a , b ; scanf("%d%d", &a , &b ); G[a].push_back(b); G[b].push_back(a); } dfs( 1 , 0 ); printf("%d", min(dp[1][0] , dp[1][1] )); return 0; }
- 1
信息
- ID
- 2422
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 35
- 已通过
- 11
- 上传者