XJOI CBH的发展计划(树上差分)

这是qzh的第二题

题目大意:

给你一棵树和一些连接祖先和孩子的边(非树枝边,类似于有向图返祖边)

让你求出删掉其中一条树枝边和一条非树枝边使图不联通的方案数

我们思考对树枝边统计答案

如图

对于红边统计答案,它的子树中有一条向外连的边,必须删掉红边和这条边才能使图不连通,所以这条树枝边贡献为1

如图

对于红边统计答案,它的子树中有0条向外连的边,删掉红边和任意一条虚线边能使图不连通,所以这条树枝边贡献为非树枝边的数量

如图

对于红边统计答案,它的子树中有两条及以上向外连的边,删掉红边和任意一条虚线边不能使图不连通,所以这条树枝边贡献为0

/-----------------------------------------------------------------/

那么问题就转化为求子树中有多少向外连的边,那就树上差分一下,把非树枝边连接的两个点中,深度较深的点标记+1,深度较浅的点标记-1,统计一个点的向外连的边就是统计子树中标记和.

然后就非常简单

代码:

%:pragma GCC optimize(3)
#include<cstdio>
#include<vector>
using namespace std;
const int N=4000010,M=8000010,P=24;
long long ans;
int fi[N],ne[M],b[M],deep[N],value[N],n,m,k,x,y,flag;
vector<int>e1,e2;
void add(int x,int y){
    b[++k]=y; ne[k]=fi[x]; fi[x]=k;
}
void dfs(int x,int fa){
    deep[x]=deep[fa]+1;
    for (int j=fi[x]; j; j=ne[j])
    if (b[j]!=fa) dfs(b[j],x);
}
int getans(int x,int fa){
    int res=value[x];
    for (int j=fi[x]; j; j=ne[j])
    if (b[j]!=fa){
        int k=getans(b[j],x);
        if (k==0) ans+=e1.size();
        else if (k==1) ans++;
        res+=k;
    }
    return res;
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1; i<=m; i++){
        scanf("%d%d%d",&x,&y,&flag);
        if (flag==1) add(x,y),add(y,x);
        else e1.push_back(x),e2.push_back(y);
    }
    dfs(1,1);
    for (int i=0; i<e1.size(); i++){
        x=e1[i]; y=e2[i];
        if (deep[x]>deep[y]) x^=y^=x^=y;
        value[y]++,value[x]--;
    }
    getans(1,1);
    printf("%lld",ans);
    return 0;
}

/----------------------------------------------------------------/

想必到这里都非常简单,那么如果,非树枝边可以连接两个没有祖先和子孙关系的点呢?

没区别,只要对这种边打标记时,对与连接的两个点标记+1,他们的lca标记-1即可

时间: 2024-11-07 17:16:45

XJOI CBH的发展计划(树上差分)的相关文章

Noip2015 运输计划 树上差分 二分答案

Code: #include<cstring> #include<cstdio> #include<algorithm> #include<string> using namespace std; void setIO(string a){freopen((a+".in").c_str(),"r",stdin);} #define maxn 300090 #define logn 20 int head[maxn],t

【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分

4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 703  Solved: 461[Submit][Status][Discuss] Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui

BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)

题意:中文题. 析:首先二分是很容易想出来的,然后主要是判断这个解合不合法,先二分答案 mid,因为有 m 个计划,所以只要添加虫洞的肯定是所有的时间长于 mid 的计划 中,也就是是那些的共同边,这个就可以用树上差分来做了,假设 s 到 t,那么让in[s]++,in[t]++,in[lca(s, t)] -= 2,其中in 表示的是 该结点与其父结点的边的计数,最后再跑一次dfs,把所有的权值都累加上去,这样就能知道哪些是共同的边了. 代码如下: #pragma comment(linker

NOIp2015 运输计划 [LCA] [树上差分] [二分答案]

我太懒了 吃掉了题面 题解 & 吐槽 一道很好的树上差分练习题. 不加fread勉强a过bzoj和luogu的数据,加了fread才能在uoj里卡过去. 可以发现,答案则是运输计划里花费的最大值,最大值最小,便是二分答案的标志. 那么该怎么check呢... 我们得找出所有超过限制的计划,这个过程可以在LCA倍增的过程中预处理出来. 然后再找出一些被这些计划都覆盖的边,找到最大的那条边,如果最大的计划花费减去最大的那条边小于x,那么x就是可行的. 但是该怎么找到那些被计划都覆盖的边呢... 我们

P2680 运输计划[二分+LCA+树上差分]

题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n?1 条双向航道,每条航道建立在两个星球之间,这 n-1n?1 条航道连通了 LL 国的所有星球. 小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 u_i*u**i* 号星球沿最快的宇航路径飞行到 v_i*v**i* 号星球去.显然,飞船驶过一条航道是需要时间的,对于航道 jj,任意飞船驶过它所花费的时间为 t_j*t**j*,并且任意两艘飞船之间不会产生任

[填坑]树上差分 例题:[JLOI2014]松鼠的新家(LCA)

今天算是把LCA这个坑填上了一点点,又复习(其实是预习)了一下树上差分.其实普通的差分我还是会的,树上的嘛,也是懂原理的就是没怎么打过. 我们先来把树上差分能做到的看一下: 1.找所有路径公共覆盖的边 例题:[NOIP2015]运输计划 (然而我还没过就先不讲了) 反正就是中间有一步要求一条边被所有计划公共覆盖. 那么怎么求它呢?暴力(滚粗).我们有一个非常好的方法就是树上差分(记录tmp为差分数组) 询问操作为从叶子节点的权值向上累加到root 在一条路径u→ v,如果tmp[u]++,那么我

树上差分总结

最近翻了一下自己的U盘,突然发现有一个树上差分的ppt,居然还没有学,因为以前以为这个很高大尚,以为很难.......(其实真的不难) 好吧,入正题 首先得知道差分这个东西吧!简单差分 在讲树上差分之前,首先需要知道树的以下两个性质:(1)任意两个节点之间有且只有一条路径.(2)一个节点只有一个父亲节点(即只有一条返祖边) 可以发现所有树上两点 a,b 的路径可拆为:a--->LCA(a,b),LCA(a,b)--->b(最好去学一下LCA的快速求法(这个我没写,随便上网找了一个感觉比较好的:

浅谈树上差分的具体应用

树上差分利用前缀和的思想,利用树上的前缀(也就是子树和),记录树上的一些信息,因为它可以进行离线操作,复杂度O(n),也是非常的好用. 最大流 FJ给他的牛棚的N(2≤N≤50,000)个隔间之间安装了N-1根管道,隔间编号从1到N.所有隔间都被管道连通了. FJ有K(1≤K≤100,000)条运输牛奶的路线,第i条路线从隔间si运输到隔间ti.一条运输路线会给它的两个端点处的隔间以及中间途径的所有隔间带来一个单位的运输压力,你需要计算压力最大的隔间的压力是多少. 这道题需要让我们求出每个点的覆

差分 and 树上差分

差分数组 定义 百度百科中的差分定义 //其实这完全和要讲的没关系 qwq 进去看了之后是不是觉得看不懂? 那我简单概括一下qwq 差分数组de定义:记录当前位置的数与上一位置的数的差值. 栗子 容易发现的是,\(\sum_{1}^{i}{b_i}\)即代表\(a_i\) 的值. \((\sum_{1}^{i}\) 即代表从1累加到i.) 思想 看到前面的\(\sum_{1}^{i}\) 你一定会发现这是前缀和! 那你认为这是前缀和? 的确是qwq. 实际上这并不是真正意义上的前缀和. 前缀和的