• Luogu-P2016 战略游戏


    题目

    题目链接

    测试得分:  100

    主要算法 :  树型DP、点的最小覆盖,二分图(匈牙利算法)

    题干:

       点的最小覆盖

    应试策略:

    1. 定义状态dp[u][0/1]表示u这个节点不放/放士兵

    2. 根据题意,如果当前节点不放置士兵,那么它的子节点必须全部放置士兵,因为要满足士兵可以看到所有的边,所以dp[u][0]+=dp[to][1]其中to是u的子节点

    3. 如果当前节点放置士兵,它的子节点选不选已经不重要了(因为树形dp自下而上,上面的节点不需要考虑),所以dp[u][1]+=min(dp[to][0],dp[to][1])

      代码

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define FORa(i,s,e) for(int i=s;i<=e;i++)
    #define FORs(i,s,e) for(int i=s;i>=e;i--)
    
    using namespace std;
    const int N=1500,M=1500;
    int n,m,root,num_edge,head[N+1],f[N+1][2];
    //f[i][0]表示的是在以i为根的子树中,不选i的最小覆盖数,f[i][1]表示的是在以i为根的子树中,选i的最小覆盖数
    struct Edge{
        int next,to;
    }edge[2*M+2]; 
    void Add_edge(int from,int to) {edge[++num_edge]=(Edge){head[from],to},head[from]=num_edge;}
    inline int min(int fa,int fb){return fa<fb?fa:fb;}
    int Dp(int u,int fa)
    {
        f[u][1]=1,f[u][0]=0;//初始化 
        for(int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(v!=fa) Dp(v,u),f[u][0]+=f[v][1],f[u][1]+=min(f[v][0],f[v][1]);
            //如果u选,则答案是子树最小覆盖和的最小值    
            //如果u不选,则答案是子树选的最小覆盖和的最小值    
        }
    }
    int main()
    {
        int from,to,fcnt;
        scanf("%d",&n);
        memset(f,127,sizeof(f));//初始化 
        FORa(i,1,n)
        {
            scanf("%d%d",&from,&fcnt);
            FORa(j,1,fcnt) scanf("%d",&to),Add_edge(from,to),Add_edge(to,from);
        }
        root=1,Dp(root,-1);
        printf("%d",min(f[root][0],f[root][1]));
        return 0;
    }
    /*4
    0 1 1
    1 2 2 3
    2 0
    3 0*/

    总结:

      1.确定建立模型

      2.构建知识架构,模型体系

  • 相关阅读:
    向量场中的积分
    Oracle 动态视图4 V$SESSION_WAIT & V$SESSION_EVENT
    Oracle 动态视图3 V$SESSION
    Oracle 动态视图2 V$LOCKED_OBJECT
    Oracle 摘去数据块的面纱
    Oracle 动态视图1 V$LOCK
    Oracle Lock 概述
    Oracle 监听动态注册与静态注册
    Oracle用户进程跟踪
    Oracle SGA参数调整
  • 原文地址:https://www.cnblogs.com/SeanOcean/p/11313963.html
Copyright © 2020-2023  润新知