P2597 [ZJOI2012]灾难【支配树】

2023-11-02

题目链接


  这是一道支配树的模板题了,然后写一下我初见支配树的理解。

  第一次碰到支配树是在昨天的多校第三场的1002,当时我推了个拓扑排序加上LCA的求差( dp[a] + dp[b] - dp[lca(a, b)] )来解这个问题,然后为了处理出来每个的dp值,我想到的方法就是用并查集加上拓扑排序的维护,结果,没有维护好,就没有过样例了,尴尬。

  后来知道了昨天的这个问题的正解是支配树,然后就开始学习了这个新的知识。

  支配树解决什么问题呢?就是解决从s起点到t终点的必经之点有哪几个。刚好也是我那时候所要的东西了。

  然后这道题呢,是一个以食物链作为背景的这样一个问题,如果食物链上的某个物种灭绝,会影响到多少其他的物种?

  那么,不就是个很纯粹的支配树的问题了吗?我们要求的支配点,不就是从任意一点到祖先链上的必经点的数量了吗?

  支配树的建立标准是怎样的呢?做了这道题的思路就是我们把每个点连到它的最近的支配点(必经点)上去,然后这样就可以累加了,就相当于是在处理一个树的子节点的和问题了。并且由于这是个DAG的图,所以不会存在环,我们可以保证最后加上超级源点0的图一定是一棵完整的支配树。

  步骤:

(1)、拓扑排序;

(2)、根据LCA,求每个点的最近必经点的位置。这里由于是拓扑排序过的,所以就保证了这个序列上的一定是从树根往树枝上去的;

(3)、建立支配树。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(x, y) make_pair(x, y)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 65540;
int N, du[maxN], tpsort[maxN], tp, siz[maxN], root[maxN][18], deep[maxN];
vector<int> g[maxN], rg[maxN], ng[maxN];
queue<int> Q;
inline void tuopu()
{
    for(int i=1; i<=N; i++) if(!du[i])
    {
        Q.push(i);
        g[0].push_back(i);
        rg[i].push_back(0);
    }
    tpsort[++tp] = 0;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop(); tpsort[++tp] = u;
        int len = (int)g[u].size();
        for(int i=0, v; i<len; i++)
        {
            v = g[u][i];
            du[v]--;
            if(!du[v]) Q.push(v);
        }
    }
}
inline int _lca(int u, int v)
{
    if(deep[u] < deep[v]) swap(u, v);
    int tmp = deep[u] - deep[v];
    for(int i=log2(1. * tmp); i>=0; i--)
    {
        if((1<<i) & tmp) u = root[u][i];
    }
    if(u == v) return u;
    for(int i=log2(1. * N); i>=0; i--)
    {
        if(root[u][i] != root[v][i])
        {
            u = root[u][i];
            v = root[v][i];
        }
    }
    return root[u][0];
}
void dfs(int u)
{
    siz[u] = 1;
    int len = (int)ng[u].size();
    for(int i=0, v; i<len; i++)
    {
        v = ng[u][i];
        dfs(v);
        siz[u] += siz[v];
    }
}
int main()
{
    scanf("%d", &N);
    for(int i=1, x; i<=N; i++)
    {
        scanf("%d", &x);
        while(x)
        {
            g[x].push_back(i);
            rg[i].push_back(x);
            du[i]++;
            scanf("%d", &x);
        }
    }
    tuopu();
    for(int u=2, x; u<=tp; u++)
    {
        x = tpsort[u];
        int len = (int)rg[x].size(), y = rg[x][0];
        for(int i=1, v; i<len; i++)
        {
            v = rg[x][i];
            y = _lca(y, v);
        }
        ng[y].push_back(x);
        deep[x] = deep[y] + 1;
        root[x][0] = y;
        for(int i=0; i<=log2(1. * N); i++) root[x][i + 1] = root[root[x][i]][i];
    }
    dfs(0);
    for(int i=1; i<=N; i++) printf("%d\n", siz[i] - 1);
    return 0;
}
/*
6
0
1 0
1 0
1 0
3 0
2 4 5 0
ans:5 0 1 0 0 0
*/

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

P2597 [ZJOI2012]灾难【支配树】 的相关文章

  • 东北大学acm第五周周赛

    include
  • Connections between cities 【HDU - 2874】【在线LCA算法】

    题目链接 昨天刚学了在线LCA 今天就来硬刚这道题还是花了一整天的时间 不过对于LCA却有了更多的理解 这道题在讲述不同根的做法上尤其是很好的 题目告诉我们有N个节点和M条边 以及C次询问 每次查询的是 L R 这两个节点间的距离 还是算得
  • True Liars 【POJ - 1417】【种类并查集+0-1背包】

    题目链接 题目想要知道有P个好人 说真话的人 和Q个坏人 说假话的人 并且有N条信息 代表A说B是好人 yes 坏人 no 那么 在保证答案唯一的情况下输出这P个好人 并且最后的时候输出 end 否则 输出 no 坑点 答案唯一指的是最后你
  • LeetCode-剑指 Offer II 114. 外星文字典,BFS 搜索算法及图的表示

    剑指 Offer II 114 外星文字典 现有一种使用英语字母的外星文语言 这门语言的字母顺序与英语顺序不同 给定一个字符串列表 words 作为这门语言的词典 words 中的字符串已经 按这门新语言的字母顺序进行了排序 请你根据该词典
  • 【斯坦福CS224W笔记之二】传统图机器学习的特征工程 — 节点

    Traditional Methods for ML on Graphs 是根据同济子豪兄学长的中文讲解做的笔记哦 感兴趣的话可以直接去b站观看详细视频 传送带 https github com TommyZihao zihao cours
  • P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib【普及】

    USACO1 5 特殊的质数肋骨 Superprime Rib 题目描述 农民约翰的母牛总是产生最好的肋骨 你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们 农民约翰确定他卖给买方的是真正的质数肋骨 是因为从右边开始切下肋骨 每次
  • Codeforces Round 867 (Div. 3)(A题到E题)

    链接 Dashboard Codeforces Round 867 Div 3 Codeforces 头一次div3做出来四题 第五题也差临门一脚 赛后看到别人e题跟自己几乎一样的思路肠悔青了 还得练才行 A TubeTube Feed 签
  • 图论17(Leetcode864.获取所有钥匙的最短路径)

    用二进制表示获得的钥匙 假设n 钥匙个数 000000000代表没有钥匙 0000000001代表有idx为1的钥匙 0000000011代表有idx 1 2的钥匙 这方法巧妙又复杂 代码 class Solution static int
  • 2021级新生个人训练赛第38场

    问题 A chicken 题目描述 小 x 非常喜欢小鸡翅 他得知 NSC 超市为了吸引顾客 举行了如下的活动 一旦有顾客在其他超市找到更便宜的小鸡翅 NSC 超市将免费送给顾客 1000g 小鸡翅 小 x 为了尽可能的省钱 走遍了各大超市
  • Financial Crisis【点双连通分量】

    题目链接 HDU 3749 你以为学了Tarjan会写几个边双就真的理解什么是双连通分量了吗 我原来真的不懂什么叫做点双BCC 不过这都没有关系 解决了这个问题之后 我终于知道了什么叫做点双连通分量了 这是一个绝对绝对经典的问题 首先讲一下
  • Even Degree【2020 年 “游族杯”E题】【欧拉回路】

    题目链接 题意 有N个点 M条边 每次可以删去一条两端点的度不都是奇数的边 问最多可以删除几条边 题目保证初始所有点度为偶数 首先 题目保证了初始的时候所有的点的度都是为偶数的 于是原图中的每一个联通块一定是一个欧拉回路 对于欧拉回路 最好
  • 离散数学第一章总结

    离散数学第一章 1 公式类型 1 重言式 也是永真式 公式真值恒为1 2 矛盾式 永假式 真值恒为0 3 可满足式 不是矛盾式的就都是可满足式 重言式一定是可满足式 2 成真赋值与成假赋值 也叫成真指派与成假指派 一组原子的取值 真值指派
  • Python,创建map

    import matplotlib pyplot as mpp import os random math matplotlib version 3 5 1 numpy version 1 21 5 创建画布及坐标轴 def set cav
  • 大学生团体天梯赛(第五届)

    题目地址 天梯赛 include
  • [图论]---[网络流]---最大权闭合子图

    最大权闭合子图 闭合图的概念 闭合图建立在有向图之上 对于 G V E 选取一个点的子集 V V 的任意一点的所有能到达的点也在集合 V 内 则称 V 为闭合子图 最大权闭合子图即在G的所有闭合子图中 点权和最大的 最大权闭合子图的求法 构
  • UVA-10603 倒水问题 题解答案代码 算法竞赛入门经典第二版

    GitHub jzplp aoapc UVA Answer 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版 使用广度优先搜索和优先队列 如果找到最小的点则退出 找不到就遍历所有的情况 include
  • hdu1827Summer Holiday【tarjan强连通分量解决最小联系费用】

    1A 撒花 这比买买买开心多了 思路 既然是强连通分量的题 很容易想到形成的东西是一坨一坨的 哈哈 然后如果某一坨入度为0 那么很不幸 这一坨只能直接被威士忌通知 至于具体通知这一坨中的哪一个 枚举一遍就知道了 最后把话费求和 感觉强连通分
  • 714阿里巴巴模拟面试

    介绍一下数据库分页 https www nowcoder com questionTerminal 3577280c810546658f06f19c01ff0345 给定一棵树 求出这棵树的直径 即两个节点距离的最大值 应该是左右子树遍历深
  • The Necklace 【UVA - 10054】【欧拉回路详解】

    题目链接1 题目链接2 题目求的是一串珠子 要让它们首尾相互照应才能串起来 并且 最后要连成一个环 使得最后的珠子的尾与第一个珠子的头相互对应 那么 这道题就是道求欧拉回路的题了 我们要先判断这是不是能够构成欧拉回路 这是个无向图 再对于需
  • 1600*B. pSort(并查集)

    解析 并查集 将能够交换的位置相连 查看对应的位置能够交换 include

随机推荐