• poj3585(树形dp,换根法)


    换根法思想为,

    1,随便找一个点作为根进行dp,

    2,再以原来点为根进行dp,此次dp,设最优解为 f[x],那么f[root]=d[root],这是显而易见的

    然后再通过找d[son]与f[x]之间关系进行dp

    比如本道题,若f[x]已知最优解,那么把son换成根,f[x]的最优解即为  d[v]+f[x]-min(d[v],w(x,v))

    类似点分治求重心,通过与父亲值做减法,求出树上除v子树外最优值

    &&&&&此种类型适用于,给出一棵树,要以每个点为根做一次dp的题目

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    struct my{
           int v;
           int next;
           int w;
    };
    
    const int maxn=500000+10;
    
    int adj[maxn],fa,dp[maxn],root,du[maxn],f[maxn],ans;
    my bian[maxn*2];
    bool vis[maxn];
    
    void myinsert(int u,int v,int w){
         bian[++fa].v=v;
         bian[fa].next=adj[u];
         adj[u]=fa;
         bian[fa].w=w;
    }
    
    void dfs1(int x){
         vis[x]=true;
         //dp[x]=0;
         for (int i=adj[x];i;i=bian[i].next){
            int v=bian[i].v;
            if(!vis[v]){
                dfs1(v);
                if(du[v]!=1) dp[x]+=min(bian[i].w,dp[v]);
                else dp[x]+=bian[i].w;
            }
         }
    }
    
    void dfs2(int x){
         vis[x]=true;
         for (int i=adj[x];i;i=bian[i].next){
            int v=bian[i].v;
            if(!vis[v]){
                if(du[x]!=1) f[v]=dp[v]+min(f[x]-min(dp[v],bian[i].w),bian[i].w);
                else {
                        f[v]=dp[v]+bian[i].w;
                       // printf("%d ",x);
                }//此时x为根
                ans=max(f[v],ans);
                dfs2(v);
            }
         }
    }
    
    int main(){
        int t,u,v,w,n;
        scanf("%d",&t);
        while(t--){
            fa=0;
            ans=0;
            memset(vis,0,sizeof(vis));
            memset(bian,0,sizeof(bian));
            memset(dp,0,sizeof(dp));
            memset(du,0,sizeof(du));
            memset(adj,0,sizeof(adj));
            memset(f,0,sizeof(f));
            scanf("%d",&n);
            for (int i=1;i<n;i++){
                scanf("%d%d%d",&u,&v,&w);
                du[u]++;
                du[v]++;
                myinsert(u,v,w);
                myinsert(v,u,w);
            }
            root=1;
            dfs1(root);
            memset(vis,0,sizeof(vis));
            f[root]=dp[root];
            dfs2(root);
            printf("%d
    ",ans);
        }
    return 0;
    }
  • 相关阅读:
    罗技 M280 无线鼠标 All In One
    How to use macOS to connect to Raspberry Pi without the monitor All In One
    lodashes All In One
    Raspberry Pi 5 All In One
    Vite All In One
    GitHub & All Contributors All In One
    Vite 运行 TypeScript 文件原理剖析 All In One
    VNC Viewer All In One
    python中 把每条FASTA序列分割成特定个数个字母一行的序列
    c 语言中实现数组元素的逆向排列
  • 原文地址:https://www.cnblogs.com/lmjer/p/9418902.html
Copyright © 2020-2023  润新知