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