[CSP校内集训]attack(DAG支配树)

题意

给一个DAG,多次询问,每次给定\(k\)个点,求1到这些点的必经点的交集大小

思路

支配树裸题,建好DAG的支配树后\(k\)个点LCA的深度即为答案

Code

#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,m,q;
int rd[N],f[N][18],dep[N];

struct Edge
{
    int next,to;
}edge[N<<1],edge1[N<<1];int head[N],head1[N],cnt,cnt1;
void add_edge(int from,int to) {edge[++cnt].next=head[from]; edge[cnt].to=to; head[from]=cnt;}
void add_edge1(int from,int to) {edge1[++cnt1].next=head1[from]; edge1[cnt1].to=to; head1[from]=cnt1;}

template <class T>
void read(T &x)
{
    char c;int sign=1;
    while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}
int lca(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=17;i>=0;--i) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
    if(x==y) return x;
    for(int i=17;i>=0;--i) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}
void toposort()
{
    queue<int> q;
    q.push(1);
    while(!q.empty())
    {
        int u=q.front(),now=-1; q.pop();
        for(int i=head1[u];i;i=edge1[i].next)
        {
            int v=edge1[i].to;
            if(now==-1) now=v;
            else now=lca(now,v);
        }
        if(now==-1) dep[u]=1;
        else
        {
            dep[u]=dep[now]+1;
            f[u][0]=now;
            for(int i=1;i<=17;++i) f[u][i]=f[f[u][i-1]][i-1];
        }

        for(int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(--rd[v]==0) q.push(v);
        }
    }
}
int main()
{
    freopen("attack.in","r",stdin);
    freopen("attack.out","w",stdout);
    read(n);read(m);read(q);
    for(int i=1;i<=m;++i)
    {
        int x,y;
        read(x);read(y);
        add_edge(x,y);
        add_edge1(y,x);
        ++rd[y];
    }
    toposort();
    while(q--)
    {
        int k; read(k);
        int x,y; read(x);
        for(int i=2;i<=k;++i)
        {
            read(y);
            x=lca(x,y);
        }
        printf("%d\n",dep[x]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Chtholly/p/11730093.html

时间: 2024-08-29 14:58:42

[CSP校内集训]attack(DAG支配树)的相关文章

[CSP校内集训]矩形面积交(树状数组)

题意 给\(n\)个互不相交的矩形,再给\(m\)个询问,每次给一个矩形求它与这\(n\)个矩形的面积交 思路 自己写的太丑了导致DEBUG了一个半小时qwq 一对矩形的交可以拆分成二维前缀和形式下的矩形的交,于是变成判断16次矩形的交(不想画图...只想口胡) 这些矩形都有\(x_0=0,y_0=0\),即左下角为坐标原点,于是一个矩形可以只用右上角的坐标表示: 对于一个询问的矩形\((x,y)\)和另一个矩形\((x_i,y_i)\),它们的交为\(min(x,x_i)\times min(

[CSP校内集训]tree(期望DP)

题意 给一颗树,从1节点出发,走每条边的概率相同且耗时为1,求每个点第一次被遍历到的期望时间(\(t_1=1\)) 思路 在树上只有两种移动方式:从儿子到父亲,从父亲到儿子 假设从\(rt\)走到\(v\)的期望代价为\(dow_i\),从\(i\)走到\(rt\)的期望代价为\(val_i\) 假设从\(rt\)转移到\(v\),\(rt\)的度数为\(k\),\(rt\)的父亲为\(fa\),则: \[dow_v = \frac{1}{k} + \sum_{son}^{son\neq v}

[CSP校内集训]pestc(拓扑排序)

题意 给一个边带权的有向图,可以花费边权使得一条边反向:通过翻转边让原图变成一个DAG,要求是所有花费中的最大值最小\(,(n,m\leq 200000)\),保证无重边和自环 解法1 考场上没看出来性质,于是口胡了一个乱搞做法 连好边后直接对原图进行一遍拓扑排序,由于原图不是DAG,所以会有无法入队的环存在:如果当前队列为空而有点没有被遍历到,那么就强行选择一个点将连向它的边翻转: 具体的,我们选择\((max(\) 连向\(i\)的边 \())\)最小的\(i\),由于翻转了连向\(i\)的

[CSP校内集训]贪吃蛇(阿尔法-贝塔剪枝)

题目 有两条蛇(1号蛇和2号蛇)在n行m列的地图上,地图上有障碍物.一条蛇碰到蛇身/障碍物/边界就会死.蛇身会不断长长--可以理解为蛇尾位置不会变,蛇只会向前伸展不会缩尾巴.两条蛇都绝顶聪明,如果自己能赢,一定会尽量快地赢;如果自己会输,一定会死得尽量晚.给出初始局面,两蛇轮流走,每次可以且必须向上下左右移动一格.1号蛇先走,请告诉我谁会在多少回合时赢.\((n,m\leq 20)\)且\(0\)的数量不超过\(50\) \(\alpha - \beta\)剪枝 AlphaBeta剪枝算法是一个

[CSP校内集训]rank

题意 给出一个字符串后缀排序之后的数组\(sa_i\),求原字符串(字典序最小),无解输出-1 思路 显然从\(rk_1\)开始填字符是可以保证字符单调不降的 找到\(sa\)值相邻的两个位置,现在需要知道\(rk_i\)和\(rk_{i+1}\)是否可以填相邻字符:当它们填相同字符时需要比较后一位,如果相对关系相同则可行(因为后一位默认已经成立) 举个栗子:\(4,2,3,1\),查看4能不能和3填同一个字符,则判断后一位2和1:而\(4>3 \&\& 2>1\),所以可以相

hdu 6604 DAG上的支配树(灭绝树)

http://acm.hdu.edu.cn/showproblem.php?pid=6604 很裸的支配树/灭绝树题 一般图的tarjan算法的话,先建立,反向图,然后建立一个超级源点,然后连到几个起点,跑支配树就行 可惜太慢...过不去 #pragma GCC optimize("Ofast") #include<bits/stdc++.h> #define endl '\n' #define ll long long #define ull unsigned long

支配树学习笔记

支配树(dominator tree) 学习笔记 学习背景 本来本蒟蒻都不知道有一个东西叫支配树……pkuwc前查某位的水表看见它的大名,甚感恐慌啊.不过好在pkuwc5道题(嗯?)都是概率期望计数,也不知是好还是不好,我在这些方面也只是不好不差……扯远了. 考挂之后也没什么心思干别的,想起支配树这个东西,于是打算学一下. 技能介绍(雾) 支配树是什么?不如直接讲支配树的性质,从性质分析它的定义. 先大概讲一下它是来求什么的. 问题:我们有一个有向图(可以有环),定下了一个节点为起点s.现在我们

支配树学习日志

支配树 学习日志 给定一张有向图 $G=(V, E)$,其中 $\lvert V \rvert=n, \lvert E \rvert=m$,以及根 $r \in V$. 我们称顶点 $x\ (x \ne r)$ 可达,当且仅当存在一条从 $r$ 到 $x$ 的路径. 对于 $x \ne r$ 且可达的 $x$,如果 $y \ne x$,且删去 $y$ 后 $x$ 不可达,那么就说 $y$ 支配 $x$.特别地,$r$ 一定支配 $x$. 不可达的点的支配点没有定义,因此我们不妨设 $G$ 的所有

有向图上支配树

按照论文的做法  引入半支配点 然后用处理DAG图的做法去处理支配树即可 存模板 #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set>