SEERC 2017 L Divide and Conquer(树上差分)

题意

给定贡献节点的两棵树,问最少割几条边导致存在一对点在这两颗树上都不在同一联通块内。并同时求出方案数

题解

  1. 容易发现最小割边数不会超过3个
    证明:一棵树产生 2 ⋅ ( n − 1 ) 2 \cdot (n-1) 2(n1)个度,因此该图存在 4 ⋅ ( n − 1 ) 4 \cdot (n-1) 4(n1)个度因此容易看出最小度的结点度数不会超过4,因此最差我们只要取最小度的结点将其度全部割掉必满足题意,证毕
  2. 容易观察出答案不可能为1,因此考虑答案为2、3,其中必定有一颗树只会割去一条边。
    因此我们只要遍历每条边割去后还需要割掉的最小边数即可,我们知道对于这类问题,可以想到,割掉这条边必定导致 u , v u,v u,v两点分开,因此我们只要能计算出使u,v在另一树也分割至少需要割几次即可。在这里我们定义确定仅仅割一条的边的树为A树,另一颗为B树,因此我们只要做一下操作即可得到答案
    1. 枚举B树上的所有边,对于A树进行 u , v u,v uv的路径(边)覆盖。
    2. 跑出差分结果,其边值即位A树割掉该边B树至少需要割多少边才能保证不连通。之后更新答案即可。注意:该处答案需要加回A边的割数1
  3. 若答案是2直接输出答案,若不是2,则需要交换两树再跑一遍答案。

代码:

/**
 *     author:     TelmaZzzz
 *     create:     2019-08-30-11.25.41
**/
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
//#include <random>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
void _R(int &x) {
    scanf("%d", &x); }
void _R(ll &x) {
    scanf("%lld", &x); }
void _R(db &x) {
    scanf("%lf", &x); }
void _R(char &x) {
    scanf(" %c", &x); }
void _R(char *x) {
    scanf("%s", x); }
void R() {
   }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值