首页 > 其他分享 >P2016题解

P2016题解

时间:2023-02-05 13:55:39浏览次数:37  
标签:int 题解 P2016 tot edge 放置 void dp

P2016题解

题目描述

Bob要建立一个古城堡,城堡中的路形成一棵无根树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能瞭望到所有的路。

注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被瞭望到。

请你编一程序,给定一树,帮 Bob 计算出他需要放置最少的士兵。

题目分析

题目需要求解最少士兵数量,数据规模不大,可以使用树上dp求解。

考虑 \(dp\) 数组表示的意义:由于每个点都可以放或者不放,而这两种情况又会对周围的点产生不同的影响

我们用 \(dp_{i,j} (j \in [0,1])\) 来表示第 \(i\) 个点放置/不放置时所需要的最小花费。

如何满足无后效性的要求?使用 \(dfs\),从深度大的节点向深度小的节点转移即可。

考虑转移方程:

  • 若点 \(i\) 不放置,则与 \(i\) 相连的所有节点都需要放置士兵。转移方程为 \(dp_{i,0} = \sum dp_{to,1}\)。
  • 若点 \(i\) 放置,则与 \(i\) 相连的点可以选择放置会不放置。转移方程为 $dp_{i,1} = \sum \min{dp_{to,0},dp_{to,1}}。

题目代码如下:

//author : yuhang-ren
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define max_n 1511
void read(int &p)
{
    p = 0;
    int k = 1;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-')
        {
            k = -1;
        }
        c = getchar();
    }
    while (c >= '0' && c <= '9')
    {
        p = p * 10 + c - '0';
        c = getchar();
    }
    p *= k;
    return;
}
void write_(int x)
{
    if(x < 0)
    {
        putchar('-');
        x = -x;
    }
    if(x>9)
    {
        write_(x/10);
    }
    putchar(x%10+'0');
}
void writesp(int x)
{
    write_(x);
    putchar(' ');
}
void writeln(int x)
{
    write_(x);
    putchar('\n');
}
struct node
{
    int to,nxt;
}edge[2*max_n];
int n,dp[max_n][2],head[max_n],tot;
void add(int u,int v)
{
    edge[++tot].to = v;
    edge[tot].nxt = head[u];
    head[u] = tot;
}
int ans = 0;
void dfs(int u,int fa)
{
    dp[u][0] = 0; 
    dp[u][1] = 1;
    for(int i = head[u];i;i = edge[i].nxt)
    {
        int v = edge[i].to;
        if(v == fa)
        {
            continue;
        }
        dfs(v,u);
        dp[u][0] += dp[v][1];
        dp[u][1] += min(dp[v][0],dp[v][1]);
    }
}
signed main()
{
    #if _clang_
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif 
    read(n);
    int u,num,v;
    for(int i = 1;i<=n;i++)
    {
        read(u),read(num);
        for(int j = 1;j<=num;j++)
        {
            read(v);
            add(u,v);
            add(v,u);
        }
    }
    dfs(0,-1);
    writeln(min(dp[0][0],dp[0][1]));
    return 0;
}

标签:int,题解,P2016,tot,edge,放置,void,dp
From: https://www.cnblogs.com/yuhang-ren/p/17093292.html

相关文章

  • CF1666K Kingdom Partition 题解
    神仙网络流题。Description传送门Solution考虑最小割,将每个点\(u\)拆成\(L_u,R_u\)两个点。对于每一条原图中的边\((u,v,w)\),连双向边\((L_u,R_v,w),(L_v,R_u,w)......
  • 题解 ARC155D Avoid Coprime Game
    题解ARC155DAvoidCoprimeGame题意给定一个可重集\(S\),保证\(\gcd_{x\inS}(x)=1\),维护一个初始为\(0\)的整数\(G\),双方轮流操作,每次每人选择\(S\)中一个数......
  • circle 题解(思维+堆)
    题目有\(n\)个圆心在\(x\)轴上的不相交的圆(存在边界重合),求这些圆将平面分为几部分。保证\(1\leqn\leq3\times10^5\),\(-10^9\leqx_i,y_i\leq10^9\)。一个......
  • CF765F Souvenirs 题解
    Preface在会压位Trie的前提下,本题最好想的做法应该是压位Trie+回滚莫队,可是竟然没人写这个做法的题解?Solution我们先转化题意:设\(a_i\)在\([l,r]\)中的前驱后继......
  • PAT乙级题解
    1001害死人不偿命的(3n+1)猜想传送门知识点:简单模拟思路:判断奇偶,根据题意即可参考代码:点击查看代码#include<iostream>usingnamespacestd;intmain(){i......
  • 题解 G. Grammar Path 2020-2021 ICPC NERC (NEERC), North-Western Russia Regional
    传送门【大意】给定一个CNF和一个有向图。有向图上的每一条边都写上了一个字母。要求你从\(s\)到\(t\)走一条尽可能短的路,且将经过的字母写下来后,这个字符串能被......
  • [JOI 2021 Final] 地牢 3 题解
    做法学习自日语酱的题解/hs/bx。本文旨在讲述我个人看完题解对此题做法的理解,可以视作对日语酱题解的注解(?。本人很菜,很可能出错,请谅解qwq。首先,对样例进行模拟,得到......
  • 最小公倍佩尔数 题解
    首先需要知道\(f\)是个啥这里直接给出结论,过程可以看大佬的博客\(f(n)=2f(n-1)+f(n-2)\)\(f(0)=0\)\(f(1)=1\)这种类似斐波那契数列的递推式有结论\(gcd(......
  • P3119 [USACO15JAN]Grass Cownoisseur G 题解
    做过的原题,模拟赛时PDF里的题面实在有点难受。首先有显然结论:在一个环上反走一定是不值的,因为环上的点本来就相互可达。所以考虑缩点。缩点后的问题可以看成:求对于每一......
  • P8368 [LNOI2022] 串 题解
    题目链接题目分析题目要求我们构造一个最长的\(T\)序列,我们首先从每个\(T_i\)入手,思考如何安排才能合法。容易观察到对于每个\(T_i\),合法的\(T_{i-1}\)有两种方......