题目

题目大意:给出两颗树的复合图(即这张图是由两颗树拼起来的),询问最小割掉多少条边,可以使得图不联通,并输出方案数。

分析

我觉得这是一道很难的题目,因为比较难想,前提结论比较多。

首先我们需要得到一个结论:就是割掉的边数不可能超过3。
证明:如果割掉的边数超过3,那么意味着每个点的度数都要≥4≥4≥4,这也就是说,图中至少需要2n2n2n条边,而图是由两个树拼成的,边数只有2n−22n−22n-2条边,显然不可能。

既然割掉的边数2≤e≤32≤e≤32≤e≤3,那么我们可以得到结论:割掉的边既有属于A树的,也有属于B树的,如果割掉的边数为2,那么说明A树一条割边,B树一条割边。
如果割掉的边数为3,那么必有一棵树只包含一条割边。

因此,我们可以发现,如果我们以其中的一棵树(举例A树,这棵树只包含一条割边)作为主树的话,相当于将这颗树切成两边,并且求交叉于这棵树两边的B树树边的数量。
如图所示:

其中红线表示切割的位置,其中割掉的边数为 AAA树1" role="presentation" style="position: relative;">111条+BBB树2" role="presentation" style="position: relative;">222条 = 333 条。

最后一个问题,怎么求A树的两个部分中B树横跨了多少边呢?
这就要用到树上差分了,由于A树的两个部分中必有一个是A树的子树,这意味着我们可以使用dfs来遍历,其次,B树的边如果链接的两个点是属于A树一个部分的时候,那么对结果没有影响。
因此,我们给B树的边(u,v)" role="presentation" style="position: relative;">(u,v)(u,v)(u,v)做如下操作mk[u]++,mk[v]++,mk[lca(u,v)]−=2;mk[u]++,mk[v]++,mk[lca(u,v)]−=2;mk[u]++,mk[v]++,mk[lca(u,v)]-=2;
这样的话,我们只需要统计A的子树有mkmkmk的和,就可以知道链接A树的两个部分有多少条B树的边了。

注意

当答案是2的时候,我们直接输出方案数即可,而当答案是3的时候,我们需要交换A、B,并再次计算方案数,因为答案是3的情况方案数可能增加。

代码

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 1e5+7;
vector<int> A[maxn],B[maxn],V[maxn];
int n,dep[maxn],pa[maxn][22],mk[maxn];
inline int getint(){int tmp;cin>>tmp;return tmp;}
int mi = 1e9,ans = 0;
void dfs(int u,int fa){pa[u][0] = fa;dep[u] = dep[fa] + 1;for(auto v : V[u]){if(v == fa) continue;dfs(v,u);}
}
#define pr(x) cout<<#x<<":"<<x<<endl
int lca(int u,int v){if(dep[u] < dep[v]) swap(u,v);int d = dep[u] - dep[v];for(int i = 0;d;i++,d >>= 1) if(d & 1) u = pa[u][i];for(int i = 20;~i;i--) if(pa[u][i] != pa[v][i]) u = pa[u][i],v = pa[v][i];if(u != v) u = pa[u][0],v = pa[v][0];return u;
}void dfs2(int u,int fa){for(int v : V[u]){if(v == fa) continue;dfs2(v,u);mk[u] += mk[v];}if(u == 1) return ;if(mk[u] + 1 < mi){mi = mk[u] + 1;ans = 1;}else if(mk[u] + 1 == mi) ++ans;
}void solve(vector<int> A[maxn],vector<int> B[maxn]){for(int i = 1;i <= n;++i) V[i].clear();for(int u = 1;u <= n;++u) for(int v : A[u]){V[u].push_back(v);V[v].push_back(u);}memset(dep,0,sizeof(dep));memset(pa,0,sizeof(pa));memset(mk,0,sizeof(mk));dfs(1,0);for(int t = 1;t <= 20;++t){for(int i = 1;i <= n;++i){pa[i][t] = pa[pa[i][t-1]][t-1];}}for(int u = 1;u <= n;++u) for(int v : B[u]){mk[v] ++,mk[u] ++,mk[lca(u,v)] -= 2;}dfs2(1,0);}
signed main()
{ios::sync_with_stdio(false);n = getint();int u,v;for(int i = 0;i < n-1;++i) {u = getint();v = getint();A[u].push_back(v);}for(int i = 0;i < n-1;++i) {u = getint(),v = getint();B[u].push_back(v);}solve(A,B);if(mi == 2) return 0*printf("%d %d\n",mi,ans);solve(B,A);cout<<mi<<' '<<ans<<endl;return 0;
}

2017 SEERC Divide and Conquer 树上差分相关推荐

  1. 解题报告:AcWing 352. 闇の連鎖(树上差分、方案统计)

    https://www.acwing.com/problem/content/354/ 在没有附加边的情况下,我们发现这是一颗树,那么再添加条附加边(x,y)后,会造成(x,y)之间产生一个环 如果我 ...

  2. 模板 - LCA最近公共祖先(倍增法、Tarjan、树上差分、LCA优化的次小生成树)

    整理的算法模板合集: ACM模板 注意x和y的LCA可以是x或者y本身 一.LCA的在线倍增算法 /*给定一棵包含 n个节点的有根无向树,有 m个询问,每个询问 给出了一对节点的编号 x和 y,询问 ...

  3. [NOIP 2015]运输计划-[树上差分+二分答案]-解题报告

    [NOIP 2015]运输计划 题面: A[NOIP2015 Day2]运输计划 时间限制 : 20000 MS 空间限制 : 262144 KB 问题描述 公元 2044 年,人类进入了宇宙纪元. ...

  4. [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分)

    [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分) 题面 给出一个无向图,以及q条有向路径.问是否存在一种给边定向的方案,使得 ...

  5. 洛谷P2680 运输计划(倍增LCA + 树上差分 + 二分答案)

    [题目链接] [思路]: 根据题意可以明显看出,当所有任务都完成时的时间是最终的结果,也就是说本题要求,求出最小的最大值. 那这样的话就暗示了将答案二分,进行check. [check方法]: 如果说 ...

  6. 差分数组 and 树上差分

    差分数组 定义 百度百科中的差分定义 //其实这完全和要讲的没关系 qwq 进去看了之后是不是觉得看不懂? 那我简单概括一下qwq 差分数组de定义:记录当前位置的数与上一位置的数的差值. 栗子 容易 ...

  7. BZOJ4771 七彩树(dfs序+树上差分+主席树)

    考虑没有深度限制怎么做.显然的做法是直接转成dfs序上主席树,但如果拓展到二维变成矩形数颜色数肯定没法做到一个log. 另一种做法是利用树上差分.对于同种颜色的点,在每个点处+1,dfs序相邻点的lc ...

  8. 洛谷 - P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并(树上差分+线段树合并)

    题目链接:点击查看 题目大意:给出一棵树,再给出 m 次操作,每次操作会选择两个点 ( x , y ) ,使得这条路径上的所有点的种类 z 加一,最后问每个点的哪个种类出现的频率最高,若多个种类出现频 ...

  9. 中石油训练赛 - One-Way Conveyors(边双缩点+树上差分)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边的无向图,现在需要将这张图转换为有向图,并且使得 k 个可达条件成立,输出一种构造方案 题目分析:如果在无向图中出现环的话,那么在转换为有向图 ...

最新文章

  1. python编程在哪里写-python3.6.3 安装好了在哪里编写程序
  2. INotifyPropertyChanged 接口 CallerMemberName属性
  3. rhel7.2 mysql_RHEL 7.2 安装 MySQL 5.7.11 二进制版
  4. linux批量创建系统,linux系统批量创建用户
  5. 中山大学计算机学院离散数学,中大信科院计算机复试专业课离散数学.pdf
  6. c51汇编语言如何定义全局变量_汇编语言程序访问C语言全局变量
  7. 老人疯狂裂变引流视频推广微信小程序源码支持定时流量主
  8. 【短时幅度谱】短时幅度谱估计在语音增强方面的MATLAB仿真
  9. 用python语言实现人工智能猴子摘香蕉的问题_人工智能猴子香蕉问题
  10. net user administrator /passwordreq:yes 错误
  11. 什么叫单模光纤_单模光纤和多模光纤的区别,以及作用是什么?
  12. 基于springboot特色农产品电商平台毕业设计-附源码211515
  13. Rushcrm:如何利用CRM系统的权限设置
  14. API,SDK和API之间的关系和区别
  15. 安卓10(Android10\API29)保存图片到相册DCIM/Camera
  16. 【金猿人物展】观远数据苏春园:用大数据赋能商业品牌 持续捕捉增长机会
  17. phpstudy php+apache 环境PHP多版本环境配置
  18. Git如何回滚代码? 1
  19. 梅斯大学的计算机专业排名,2018法国排名前50的大学一览表
  20. Eclipse新建一个Spring项目(最基础)

热门文章

  1. 缩减oracle日志,[20180829]减少日志生成量.txt
  2. 软件构造学习笔记-第六周
  3. AcWing 756. 蛇形矩阵
  4. C++set容器-大小和交换
  5. java继承层次结构,在状态模式中实现继承层次结构 - java
  6. redis api 中文文档_我的Redis学习资料库
  7. mysql数据库备份总结_MySQL数据库备份总结
  8. CF773F Test Data Generation(倍增FFT/动态规划)
  9. P2231 [HNOI2002]跳蚤(裴蜀定理/莫比乌斯反演)
  10. Codeforces Round #585 (Div. 2) F. Radio Stations 2-sat + 神仙建模