zoukankan      html  css  js  c++  java
  • 树形dp专题

    推荐一个博主写的——关于树形DP中求最小支配集,覆盖集,独立集的博客

    他写的关于树形DP代码的解释很好懂

    虽然还有求重心,树形背包什么的没讲,不过对于我这样刚入门的人来说应该是够了

    最小支配集——POJ3659

    题目含义

    有1到N个点,给出点两两的相邻关系,这个图的最小支配集

    题目分析

    简单易懂的最小支配集问题,看着链接的博客很快就能写出来

    但博客没讲一些细节问题

    比如说遇到一个无向图可以用vis数组使无向变有向,这样dfs也只用一个参数就行了

    还有根节点没有父节点,不能在求最小时加入dp[root][2]

    题目代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int maxn=1e4+7;
    const int INF=0x3f3f3f3f;
    struct node{
        int to;
        int next;
    }edge[maxn<<1];
    int head[maxn],dp[maxn][3];
    int n,a,b,tot;
    bool vis[maxn];
    int min3(int a,int b,int c){
        return min(a,min(b,c));
    }
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    void dfs(int u){
        vis[u]=true;
        dp[u][0]=1;
        dp[u][1]=dp[u][2]=0;
        int inc=INF;
        bool exist=false;
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(!vis[v]){
                dfs(v);
                dp[u][0]+=min3(dp[v][0],dp[v][1],dp[v][2]);
                dp[u][2]+=min(dp[v][0],dp[v][1]);
                if(dp[v][0]<=dp[v][1]){
                    exist=true;
                    dp[u][1]+=dp[v][0];
                }
                else{
                    inc=min(inc,dp[v][0]-dp[v][1]);
                    dp[u][1]+=dp[v][1];
                }
            }
        }
        if(!exist){
            dp[u][1]+=inc;
        }
    }
    int main(){
        scanf("%d",&n);
        memset(dp,0,sizeof(dp));
        memset(head,-1,sizeof(head));
        memset(vis,false,sizeof(vis));
        tot=0;
        for(int i=1;i<n;i++){
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        dfs(a);
        printf("%d
    ",min(dp[a][0],dp[a][1]));
        return 0;
    }
    最小支配集

    最小覆盖集——POJ1463

    题目含义

    给出N个点,以及每个点所相邻的点,求最小覆盖集

    题目分析

    与支配集相比只有两个状态,还不用讨论,简单多了

    题目代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int maxn=1e4+7;
    const int INF=0x3f3f3f3f;
    struct node{
        int to;
        int next;
    }edge[maxn<<1];
    int head[maxn],dp[maxn][2];
    int tot,t,n,m,a,root;
    char ch;
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    void dfs(int u){
        dp[u][0]=0;
        dp[u][1]=1;
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            dfs(v);
            dp[u][0]+=dp[v][1];
            dp[u][1]+=min(dp[v][0],dp[v][1]);
        }
    }
    int main(){
        while(~scanf("%d",&t)){
            memset(dp,0,sizeof(dp));
            memset(head,-1,sizeof(head));
            tot=0;
            for(int i=0;i<t;i++){
                scanf("%d%c%c%d%c",&n,&ch,&ch,&m,&ch);
                for(int j=0;j<m;j++){
                    scanf("%d",&a);
                    add(n,a);
                }
                if(!i)root=n;
            }
            dfs(root);
            printf("%d
    ",min(dp[root][0],dp[root][1]));
        }
        return 0;
    }
    最小覆盖集

    一遍过真是爽啊

  • 相关阅读:
    js 小程序获取本周七天
    js 时间处理函数 获取今天的前几天和后几天的任意一天
    路由配置
    3 vue-router 的默认hash 改mode:history去除#号 传参
    Eslint 配置及规则说明(报错)
    打开左侧菜单栏
    sublime 对vue的高亮显示
    gitlab 本地建库配置 config
    GIT 安装
    v-html的应用
  • 原文地址:https://www.cnblogs.com/helman/p/11265911.html
Copyright © 2011-2022 走看看