zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    CodeForces 203C Photographer
    CodeForces 190A Vasya and the Bus
    CodeForces 187A Permutations
    Zoj3762 等待解决
    LA4080最短路树的应用
    uva10917 dij单源最短路预处理+构造新图(DAG)+求图上路径数
    uva11374 dij单源最短路+枚举
    LA3713 2-sat(用到两种矛盾关系)
    【算法总结】2-sat中对象的5种矛盾关系及其连边方式
    LA3211二分答案+2-sat+总结的此类问题统一建模方法
  • 原文地址:https://www.cnblogs.com/lmjer/p/9418902.html
Copyright © 2011-2022 走看看