首页 > 其他分享 >AcWing 1077. 皇宫看守

AcWing 1077. 皇宫看守

时间:2023-01-18 20:12:08浏览次数:49  
标签:idx min int 1077 ne qquad 皇宫 节点 AcWing

解题思路

\(\qquad\) 题目就不再复述了,我们这题和上一题类似,可以采用树形DP + 状态机

状态表示

\[f[i][j], j\in[0,2]表示的是第 i 个点,第 j 种状态 \]

对于三种状态,有如下分类

\[f[i][0]表示的是不选当前节点,但是选择了父节点 \]

\[f[i][1]表示的是不选当前节点,但是选择了子节点 \]

\[f[i][2]表示的是选择当前节点 \]

状态转移

\(\qquad\)首先看\(f[i][0]\),假设 \(j\) 是 \(i\) 的一个子节点,\(i\) 并没有选择,所以 \(f[j][0]\) 这个状态是无法转移到 \(f[i][0]\) 的(\(i\) 就是 \(j\) 的父亲, \(i\) 都不选自己,那就是不选 \(j\) 的父亲)。所以 \(j\) 只能自给自足或者选择自己的儿子,因此:

\[\large f[i][0] = \sum_{j\in son[i]} \min\{f[j][1], f[j][2]\} \]

\(\qquad\)接下来要考虑的是 \(f[i][1]\),因为这个状态需要整颗子树的信息,所以放到后面处理

\(\qquad\) 对于 \(f[i][2]\),因为 \(i\) 已经选择了自己,所以不管子节点怎么样,都是合法的,因此可以由子节点的三种状态转移而来

\[\large f[i][2] = \sum_{j\in son[i]} \min\{f[j][1], f[j][2], f[j][0]\} \]

\(\qquad\) 问题回到了 \(f[i][1]\)的身上,我们可以进行如下分析:
\(\qquad\) 枚举 \(i\) 的所有子节点 \(j\),假设 \(j\) 是我们最终要选择的子节点,那么如果是选了这个儿子,其它儿子仍然是没有被父亲选的,所以其它儿子的代价也要加上,也就是总和去掉 \(f[j][2]\),因为前面有类似的情况 \(f[i][0]\) 已经保存了总和,那这里就不用另外处理了。

代码

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1510;
int h[N], e[N], ne[N], w[N], idx;
int st[N], root, n, f[N][3];

void add(int a, int b) 
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void dfs(int u) 
{
    f[u][1] = 1e9, f[u][2] = w[u];

    for (int i = h[u]; ~i; i = ne[i]) 
    {
        int j = e[i];
        dfs(j);

        f[u][0] += min(f[j][1], f[j][2]); //同时用作sum
        f[u][2] += min({f[j][1], f[j][0], f[j][2]});
    }

    for (int i = h[u]; ~i; i = ne[i]) 
    {
        int j = e[i];
        f[u][1] = min(f[u][1], f[u][0] + f[j][2] - min(f[j][1], f[j][2]));
    }
}

int main() 
{
    scanf("%d", &n);

    memset(h, -1, sizeof h);
    for (int i = 1; i <= n; i ++ ) 
    {
        int id, m, r, c;
        scanf("%d%d%d", &id, &c, &m);
        w[id] = c;
        while (m -- ) 
        {
            scanf("%d", &r);
            add(id, r);
            st[r] = 1;
        }
    }

    root = 1;
    while (st[root]) root ++ ;
    dfs(root);

    printf("%d\n", min(f[root][1], f[root][2]));

    return 0;
}

标签:idx,min,int,1077,ne,qquad,皇宫,节点,AcWing
From: https://www.cnblogs.com/StkOvflow/p/17060489.html

相关文章

  • AcWing. 323. 战略游戏
    题意简述\(\qquad\)给定一棵树,要求树中任意一边至少选中一点,求最少满足题意的选点数解题思路\(\qquad\)我们可以先画出示意图来橙色点表示选,灰色点表示不选。\(\qqu......
  • AcWing1075. 数字转换
    题目描述如果一个数\(x\)的约数之和\(y\)(不包括他本身)比他本身小,那么\(x\)可以变成\(y\),\(y\)也可以变成\(x\)例如,\(4\)可以变为\(3\),\(1\)可以变为\(7\)。......
  • AcWing. 1073 树的中心
    题目描述给定一棵树,树中包含\(n\)个结点(编号\(1\)~\(n\))和\(n-1\)条无向边,每条边都有一个权值。请你在树中找到一个点,使得该点到树中其他结点的最远距离最近。解题......
  • AcWing. 1072 树的最长路径
    题目描述给定一棵树,树中包含\(n\)个结点(编号\(1\)~\(n\))和\(n-1\)条无向边,每条边都有一个权值。现在请你找到树中的一条最长路径。换句话说,要找到一条路径,使得使得......
  • acwing 4700. 何以包邮?
    acwing4700.何以包邮?水一期题目描述新学期伊始,适逢顿顿书城有购书满$x$元包邮的活动,小$P$同学欣然前往准备买些参考书。一番浏览后,小$P$初步筛选出$n......
  • AcWing 786.第k个数(快速排序)
    [原链接](https://www.acwing.com/problem/content/788/题目#include<cstdio>#include<iostream>#include<cstdlib>usingnamespacestd;inta[100100];voidqu......
  • AcWing 第 86 场周赛 ABC
    https://www.acwing.com/activity/content/competition/problem_list/2794/4794.健身#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;typedefpa......
  • AcWing257 关押罪犯
    题目大意\(\qquad\)给定一张正权无向图,定义冲突值为一个集合内权值最大的边,将一张图上的点,分成两部分,不同部分的点在原图上的边作废,求最小化最大冲突值,并输出。解题思路......
  • AcWing杯 第85场周赛
    4791.死或生#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intn,ax,ay,bx,by;int32_tmain(){cin>>n;for(intt,x,......
  • ACWING 4261. 孤独的照片
    题意:给一个长度为n的只包含'G'和'H'字符串要求统计所有长度>=3且只有一个不一样的字符的子串个数思路:最开始的思路就是找到一个满足的三个字符然后向两边扩展然后......