poj3417 闇の連鎖 【树上差分】By cellur925

闇の連鎖
(yam.pas/c/cpp)
题目描述
传说中的暗之连锁被人们称为 Dark。Dark 是人类内心的
黑暗的产物,古今中外的勇者们都试图打倒它。经过研究,
你发现 Dark 呈现无向图的结构,图中有 N 个节点和两类边,
一类边被称为主要边,而另一类被称为附加边。Dark 有 N – 1
条主要边,并且 Dark 的任意两个节点之间都存在一条只由主
要边构成的路径。另外,Dark 还有 M 条附加边。
你的任务是把 Dark 斩为不连通的两部分。一开始 Dark
的附加边都处于无敌状态,你只能选择一条主要边切断。一
旦你切断了一条主要边,Dark 就会进入防御模式,主要边会变为无敌的而附加边可以被切
断。但是你的能力只能再切断 Dark 的一条附加边。现在你想要知道,一共有多少种方案可
以击败 Dark。注意,就算你第一步切断主要边之后就已经把 Dark 斩为两截,你也需要切断
一条附加边才算击败了 Dark。
输入格式
第一行包含两个整数 N 和 M。
之后 N – 1 行,每行包括两个整数 A 和 B,表示 A 和 B 之间有一条主要边。
之后 M 行以同样的格式给出附加边。
输出格式
输出一个整数表示答案。

显然,这个图上的点与主要边构成了一棵树。当加入一条附加边时,会构成环。如果我们第一次砍主要边的时候砍的是$x$->$y$路径上的某条边,那么之后再砍的附加边一定是$<x,y>$。

这样,我们的题目就转换成了一个树上差分的问题。附加边$<x,y>$会影响x到y路径上的所有边。把这些边经过的次数(受影响的次数)进行统计。若第一次砍的是覆盖0次的,那么第二步可任意切断一条附加边;若一次砍的 是覆盖1次的,第二步方法唯一;其他答案在第二步均没有其他任何方法。

实现的时候dfs和lca查询写错了两个细节,结果调了很久...气orz

Code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<queue>
 4 #include<cmath>
 5 #define maxn 100090
 6
 7 using namespace std;
 8
 9 int n,m,tot,t,ans;
10 int head[maxn],d[maxn],f[maxn][30],val[maxn];
11 struct node{
12     int to,next;
13 }edge[maxn*2];
14
15 void add(int x,int y)
16 {
17     edge[++tot].to=y;
18     edge[tot].next=head[x];
19     head[x]=tot;
20 }
21
22 void init()
23 {
24     queue<int>q;
25     q.push(1),d[1]=1;
26     while(!q.empty())
27     {
28         int u=q.front();q.pop();
29         for(int i=head[u];i;i=edge[i].next)
30         {
31             int v=edge[i].to;
32             if(d[v]) continue;
33             d[v]=d[u]+1;
34             f[v][0]=u;
35             for(int j=1;j<=t;j++)
36                 f[v][j]=f[f[v][j-1]][j-1];
37             q.push(v);
38         }
39     }
40 }
41
42 int lca(int x,int y)
43 {
44     if(d[x]>d[y]) swap(x,y);
45     for(int i=t;i>=0;i--)
46         if(d[f[y][i]]>=d[x]) y=f[y][i];
47     if(x==y) return x;
48     for(int i=t;i>=0;i--)
49         if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
50     return f[x][0];
51 }
52
53 void review(int u,int fa)
54 {
55     for(int i=head[u];i;i=edge[i].next)
56     {
57         int v=edge[i].to;
58         if(v==fa) continue;
59         review(v,u);
60         val[u]+=val[v];
61     }
62 }
63
64 int main()
65 {
66     scanf("%d%d",&n,&m);
67     t=log2(n)+1;
68     for(int i=1;i<=n-1;i++)
69     {
70         int x=0,y=0;
71         scanf("%d%d",&x,&y);
72         add(x,y);add(y,x);
73     }
74     init();
75     for(int i=1;i<=m;i++)
76     {
77         int x=0,y=0;
78         scanf("%d%d",&x,&y);
79         int fa=lca(x,y);
80         val[x]++,val[y]++;
81         val[fa]-=2;
82     }
83     review(1,0);
84     for(int i=2;i<=n;i++)
85     {
86         if(val[i]==0) ans+=m;
87         else if(val[i]==1) ans++;
88     }
89     printf("%d\n",ans);
90     return 0;
91 }

原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9726823.html

时间: 2024-11-10 13:02:59

poj3417 闇の連鎖 【树上差分】By cellur925的相关文章

树上差分:闇の連鎖 题解

题目描述 传说中的暗之连锁被人们称为 Dark. Dark 是人类内心的黑暗的产物,古今中外的勇者们都试图打倒它. 经过研究,你发现 Dark 呈现无向图的结构,图中有 N 个节点和两类边,一类边被称为主要边,而另一类被称为附加边. Dark 有 N – 1 条主要边,并且 Dark 的任意两个节点之间都存在一条只由主要边构成的路径. 另外,Dark 还有 M 条附加边. 你的任务是把 Dark 斩为不连通的两部分. 一开始 Dark 的附加边都处于无敌状态,你只能选择一条主要边切断. 一旦你切

AcWing352 闇の連鎖(树上差分+lca)

这道题的我们知道如果在两个点之间有附加边,其实就相当于在这个回路上的每条边都权值+1,这样就可以通过差分数组来快速求取大小 这里的精髓就是在输入的两个位置+1,而在他们的lca上-=2: #include<iostream> #include<queue> #include<map> #include<vector> #include<cstdio> #include<algorithm> #include<stack>

poj3417 Network 树上差分+LCA

题目传送门 题目大意:给出一棵树,再给出m条非树边,先割掉一条树边,再割掉一条非树边,问有几种割法,使图变成两部分. 思路:每一条 非树边会和一部分的树边形成一个环,分三种情况: 对于那些没有形成环的树边来说,割掉这条边,就已经使图分离,然后随便割一条非树边就可以了,所以这样的边每次答案加上m. 对于那些只存在在一个环中的树边来说,割掉这条边,再割一条和他存在于同一个环中的那条非树边,也能合法,所以加一. 对于存在于多个环中的树边,无论怎样,都无法合法. 也就是此时我们将题目转化成了树上的覆盖问

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

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

【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

【COGS 2434】 暗之链锁 树上差分+LCA

差分就是把一个值拆成许多差的和如 1 2 4 6 9 那么 把这个东西拆成 1 1 2 2 3 就是了,当然也可以理解为对一个问题分解为多个子问题并对其进行操作来得到原问题的答案. 树上差分就更玄妙了,它既可以把原问题拆成他到根节点的所有点,也可以拆成子树,拆成子树的话修改一个点影响的是他到根的路径上所有点,根据这个我们可以再加上LCA来解决许多问题. 这道题:I. 我们可以看出我们可以把它转化成一棵有根树,那么两部分一定是一个子树和其他 II. 那些虚边,都是砍断实边之后的藕断丝连,至于如何计

【CF739B】Alyona and a tree(树上差分,二分,树形DP)

题意:给出一棵有根树,树上每个点.每条边都有一个权值. 现在给出"控制"的定义:对一个点u,设点v在其子树上,且dis(u,v)≤av,则称u控制v. 要求求出每个点控制了多少个点 n (1?≤?n?≤?2·105).  (1?≤?ai?≤?109) 1?≤?pi?≤?n, 1?≤?wi?≤?109) 思路:在学校CF有时上不去不知道为什么 对于确定的点i,计算它对哪些点有贡献 dis[i]-dis[u]<=a[i] dis[u]<=a[i]-dis[i]满足二分性 倍增枚

安徽合肥濱湖世紀城連鎖經營業百分百成功嗎?保障賺錢嗎?

疑点一:上总后每个月真的有6-10万的保底工资吗?如果有怎么解释这个钱从哪里来 疑点二:为什么家族式的人都去做了? 疑点三:上平台后能挣一千多万是为了宣传还是事实? 疑点四:上老总说是买车买房时真的吗?? 疑点五:为什么老总知道行业的内幕还没办法的叫自己的家人? 疑点六:税收是交给国·家了还是老总分掉了? 疑点七:具体是怎么分配的 ?每一代老总具体是怎么拿钱的? 疑点八:上总后就不见人了?老总们每天都在干什么? 种种疑点让人猜不透,耐人寻味 ! 由于文章字数有限,在这里不能一一明说,可加扣扣 2

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

这是qzh的第二题 题目大意: 给你一棵树和一些连接祖先和孩子的边(非树枝边,类似于有向图返祖边) 让你求出删掉其中一条树枝边和一条非树枝边使图不联通的方案数 我们思考对树枝边统计答案 如图 对于红边统计答案,它的子树中有一条向外连的边,必须删掉红边和这条边才能使图不连通,所以这条树枝边贡献为1 如图 对于红边统计答案,它的子树中有0条向外连的边,删掉红边和任意一条虚线边能使图不连通,所以这条树枝边贡献为非树枝边的数量 如图 对于红边统计答案,它的子树中有两条及以上向外连的边,删掉红边和任意一条