• 树的直径变形——cf1238F


    /*
    题目给定一些一维线段[li,ri],要求从这些线段里挑出一些线段,每条线段对应一个点,如果两线段相交,那么点连边,这样得到的树是good-tree 
    现在给定一棵树,要求从该树中选出一棵子树,使这棵子树是good-tree
    
    显然不能有三个线段两两相交,这样就成了环
    对应到good-tree的性质上,就是一个根最多连两个size>1的结点,但可以挂多个size=1的结点,非根结点最多挂一个size>1的结点
     
    参照求直径的树形dp,令dp[u]表示已经连了一个size>1的儿子的最大值,当以u为根时,只要再去找另一个儿子进行匹配就可以了 
    dp[u]的初始值:u连了所有儿子,这样并不影响u的一个儿子挂链,所以要预处理出u的度数 
    */
    #include<bits/stdc++.h>
    #include<vector>
    using namespace std;
    #define N 300005
    
    vector<int>G[N];
    int n,q,dp[N],ans,d[N];
    
    void dfs(int u,int pre){
        for(auto v:G[u]){//先处理出子节点的u 
            if(v==pre)continue;
            dfs(v,u);    
        }
        
        dp[u]=d[u]-1+1;//不算pre的度数+自身 
        for(auto v:G[u]){
            if(v==pre)continue;
            ans=max(ans,dp[u]+dp[v]);
            dp[u]=max(dp[u],dp[v]+d[u]-2+1);    
        }
    }
    
    int main(){
        cin>>q;while(q--){
            cin>>n;
            for(int i=1;i<=n;i++)G[i].clear(),d[i]=0;
            for(int i=1;i<n;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                G[x].push_back(y);
                G[y].push_back(x);
                d[x]++;d[y]++;
            }
            ans=0;
            for(int i=1;i<=n;i++)dp[i]=0;
            dfs(1,1);
            cout<<ans<<'
    ';
        }
    }
  • 相关阅读:
    菜鸡的Java笔记
    Python 练习 进程
    laravel 目录结构
    mysql 操作详解
    菜鸡的Java笔记
    菜鸡的Java笔记
    菜鸡的Java笔记
    菜鸡的Java笔记 数字操作类
    【模板】多项式求逆
    交互题[CF1103B Game with modulo、CF1019B The hat、CF896B Ithea Plays With Chtholly]
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11712691.html
Copyright © 2020-2023  润新知