• 树形DP()


    没有上司的舞会

    Ural 大学有 N 名职员,编号为 1∼N。

    他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。

    每个职员有一个快乐指数,用整数 Hi 给出,其中 1≤i≤N。

    现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。

    在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值

    输入格式

    第一行一个整数 N。

    接下来 N 行,第 i 行表示 i 号职员的快乐指数 Hi。

    接下来 N−1 行,每行输入一对整数 L,K,表示 K 是 L 的直接上司。(注意一下,后一个数是前一个数的父节点,不要搞反)。

    输出格式

    输出最大的快乐指数。

    数据范围

    1≤N≤6000
    −128≤Hi≤127

    输入样例:

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

    输出样例:

    5
    

     

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. const int N=6100;
    6. int h[N],ne[N],e[N],idx;
    7. int happy[N];
    8. bool has_father[N];
    9. int f[N][2];
    10. bool st[N];
    11. int root=1;
    12. //建表
    13. void add(int a,int b)
    14. {
    15. e[idx]=b;
    16. ne[idx]=h[a];
    17. h[a]=idx++;
    18. }
    19. void dfs(int u)
    20. {
    21. f[u][1]=happy[u];//如果选当前节点u,就可以把f[u,1]先怼上他的高兴度
    22. for(int i=h[u];i!=-1;i=ne[i])
    23. {
    24. int j=e[i];
    25. dfs(j);
    26. //状态转移部分
    27. f[u][0]+=max(f[j][1],f[j][0]);
    28. f[u][1]+=f[j][0];
    29. }
    30. }
    31. int main()
    32. {
    33. int n;cin>>n;
    34. for(int i=1;i<=n;i++) cin>>happy[i];
    35. memset(h,-1,sizeof h);
    36. for(int i=1;i
    37. {
    38. int a,b;cin>>a>>b;
    39. add(b,a);
    40. //若有父节点标记一下
    41. has_father[a]=true;
    42. }
    43. //找树根 树根没有父节点
    44. while(has_father[root]) root++;
    45. dfs(root);
    46. cout<<max(f[root][0],f[root][1]);//输出不选根节点与选根节点的最大值
    47. return 0;
    48. }

    树的最长路径

    给定一棵树,树中包含 n 个结点(编号1~n)和 n−1 条无向边,每条边都有一个权值。

    现在请你找到树中的一条最长路径。

    换句话说,要找到一条路径,使得使得路径两端的点的距离最远。

    注意:路径中可以只包含一个点。

    输入格式

    第一行包含整数 n。

    接下来 n−1 行,每行包含三个整数 ai,bi,ci,表示点 ai 和 bi 之间存在一条权值为 ci 的边。

    输出格式

    输出一个整数,表示树的最长路径的长度。

    数据范围

    1≤n≤10000
    1≤ai,bi≤n
    −105≤ci≤105

    输入样例:

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

    输出样例:

    22
    

     

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. const int N=2e5+10;
    6. int h[N],ne[N],w[N],e[N],idx;
    7. int n;
    8. int ans=0;
    9. void add(int a,int b,int c)
    10. {
    11. e[idx]=b;
    12. w[idx]=c;
    13. ne[idx]=h[a];
    14. h[a]=idx++;
    15. }
    16. //father表示u的父节点,因为该图为无向图,并且迭代过程中不能回到父节点,所以要特殊标记.
    17. int dfs(int u,int father)
    18. {
    19. //因为题目描述中有:注意:路径中可以只包含一个点
    20. //所以题目中的结果一定不为负数,负的路径由此可以忽略掉
    21. int d1=0,d2=0;
    22. for(int i=h[u];i!=-1;i=ne[i])
    23. {
    24. int j=e[i];
    25. if(j==father) continue;
    26. int d=dfs(j,u)+w[i];//求出路径的长度
    27. if(d>=d1) d2=d1,d1=d; //d1,d2求出以该点为顶点的最长路径
    28. else if(d>d2) d2=d;//最长路径和次长路径
    29. }
    30. ans=max(ans,d1+d2);
    31. return d1;
    32. }
    33. int main()
    34. {
    35. cin>>n;
    36. memset(h,-1,sizeof h);
    37. for(int i=1;i
    38. {
    39. int a,b,c;cin>>a>>b>>c;
    40. add(a,b,c);
    41. add(b,a,c);
    42. }
    43. dfs(1,-1);
    44. cout<
    45. return 0;
    46. }

    D. Apple Tree

    蒂莫菲的花园里长着一棵苹果树;它是n个顶点的有根树,根在顶点1中(顶点编号从1到n)。树是一个没有循环和多条边的连通图。这棵树很不寻常,它的根向上生长。然而,对于程序员的树来说,这是很正常的。苹果树很年轻,所以上面只会长两个苹果。苹果会生长在某些顶点(这些顶点可能是相同的)。苹果长出来后,蒂莫菲开始摇晃苹果树,直到苹果掉下来。每次Timofey摇动苹果树时,每个苹果都会发生以下情况:让苹果现在位于顶点u。如果一个顶点u有一个子顶点,苹果就会移动到它上面(如果有几个这样的顶点,苹果可以移动到其中的任何一个)。否则,苹果就会从树上掉下来。可以看出,在有限的时间后,两个苹果都会从树上掉下来。Timofey有苹果可以生长的顶点的q假设。他假设苹果可以在顶点xyy中生长,并想知道苹果可以从树上掉落的顶点对(a,b)的数量,其中a——从顶点x掉落的苹果将从顶点掉落,b——从顶点yy掉落的苹果。帮他做这个。 (多组输入 并且1时根节点)

    输入样例 

    2

    5

    1 2

    3 4

    5 3

    3 2

    4

    3 4

    5 1

    4 4

    1 3

    3

    1 2

    1 3

    3

    1 1

    2 3

    3 1

     

    输出样例 

    2
    2
    1
    4
    4
    1
    2
    
    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. typedef long long ll;
    6. const int N=5e5+10;
    7. int h[N],ne[N],e[N],idx,w[N];
    8. int cnt[N];
    9. int n;
    10. void add(int a,int b)
    11. {
    12. e[idx]=b;
    13. ne[idx]=h[a];
    14. h[a]=idx++;
    15. }
    16. void dfs(int u,int father)
    17. {
    18. if(w[u]==1&&u!=1)
    19. {
    20. cnt[u]=1;
    21. return ;
    22. }
    23. for(int i=h[u];i!=-1;i=ne[i])
    24. {
    25. int j=e[i];
    26. if(father==j) continue;
    27. dfs(j,u);
    28. cnt[u]+=cnt[j];
    29. }
    30. }
    31. int main()
    32. {
    33. int t;cin>>t;
    34. while(t--)
    35. {
    36. cin>>n;
    37. memset(h,-1,sizeof 4*(n+1));
    38. memset(cnt,0,sizeof 4*(n+1));
    39. memset(w,0,sizeof 4*(n+1));
    40. for(int i=1;i
    41. {
    42. int a,b;cin>>a>>b;
    43. add(a,b);
    44. add(b,a);
    45. w[a]++;
    46. w[b]++;
    47. }
    48. dfs(1,-1);
    49. int q;
    50. cin>>q;
    51. while(q--)
    52. {
    53. int a,b;cin>>a>>b;
    54. cout<<(ll)cnt[a]*cnt[b]<
    55. }
    56. }
    57. return 0;
    58. }

     

  • 相关阅读:
    Spring Boot配置项注入异常:Failed to bind properties
    一点一点学习C++之笔记005
    tcpdump(五)命令行参数讲解(四)
    “蔚来杯“2022牛客暑期多校训练营4 L.Black Hole 垃圾计算几何
    微信小程序常用组件实战
    Conda环境配置常用
    spring的annotation-driven配置事务管理器详解
    springboot配置多数据源
    地级市市场化指数+樊纲市场化指数(包含分省、市两份数据)
    力扣 240.搜素矩阵II
  • 原文地址:https://blog.csdn.net/m0_74015873/article/details/132794019