题意:给定两棵树,一次操作形如:选一个未被选过的叶子,改变它的一条出边,问能否在第一棵树上做一些操作使得它变成第二棵树,如果能则询问最小操作次数

如果答案不是$n$,那么存在一个点$r$没有被选中过

如果$r$和$v$在两棵树上都相邻,那么我们不会改变$(v,r)$,因为如果改变了那么一定是选中$v$,以后没有办法再把这条边变回来

如果$u$和$v$在两棵树上都相邻,那么我们不会改变$(u,v)$,因为只能选叶子,所以改变这条边一定选$u$,以后要把这条边变回来只能选$v$,而$v$作为叶子的唯一出边是$(v,r)$,所以这条边也不能动

以此类推,我们从$r$开始搜索,只走那些两棵树的公共边,得到的连通块中的边是不会被改变的,连通块中的点同样不会被选中,因为它们作为叶子时唯一的出边已经被硬点为不可改变

剩下的边是一定要改变的,并且改变它只能由选定端点中更深的那个来实现,我们想知道是否存在一个合法的顺序使得按这个顺序选择点能满足每次选到的都是叶子

在第一棵树中,设$fa_x=y$,如果$x,y$都能被选,那么选$y$之前一定要先选$x$,在第二棵树中,如果$fa_x=y$且$x,y$都能被选,那么选$x$之前要先选$y$,把限制关系建成一个有向图,如果没有环就有解了

总时间复杂度$O(n)$,但这样并不能统计到答案为$n$的情况,于是我们再$O(n^2)$枚举第一次操作,被选中的那个点之后就不能选了,于是套用上面的算法即可,总时间复杂度$O(n^3)$

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int inf=2147483646;
int fb;
struct tree{
	int h[60],nex[110],to[110],M;
	void reset(){
		M=0;
		memset(h,0,sizeof(h));
	}
	void add(int a,int b){
		M++;
		to[M]=b;
		nex[M]=h[a];
		h[a]=M;
	}
	int fa[60];
	void dfs(int x){
		for(int i=h[x];i;i=nex[i]){
			if(to[i]!=fa[x]&&to[i]!=fb){
				fa[to[i]]=x;
				dfs(to[i]);
			}
		}
	}
}a,b;
int d[60],v[60],n,M;
bool f[60];
void dfs(int fa,int x){
	int i,tm;
	tm=++M;
	f[x]=1;
	for(i=a.h[x];i;i=a.nex[i])v[a.to[i]]=tm;
	for(i=b.h[x];i;i=b.nex[i]){
		if(b.to[i]!=fa&&v[b.to[i]]==tm&&b.to[i]!=fb)dfs(x,b.to[i]);
	}
}
struct graph{
	int h[60],nex[110],to[110],M;
	bool v[60],ins[60];
	void reset(){
		M=0;
		memset(h,0,sizeof(h));
		memset(v,0,sizeof(v));
		memset(ins,0,sizeof(ins));
	}
	void add(int a,int b){
		M++;
		to[M]=b;
		nex[M]=h[a];
		h[a]=M;
	}
	bool dfs(int x){
		v[x]=1;
		ins[x]=1;
		for(int i=h[x];i;i=nex[i]){
			if(!v[to[i]]){
				if(!dfs(to[i]))return 0;
			}else if(ins[to[i]])
				return 0;
		}
		ins[x]=0;
		return 1;
	}
}g;
int solve(int r){
	fb=r;
	int i,cnt;
	memset(a.fa,0,sizeof(a.fa));
	a.dfs(r);
	memset(b.fa,0,sizeof(b.fa));
	b.dfs(r);
	memset(f,0,sizeof(f));
	dfs(0,r);
	g.reset();
	cnt=0;
	for(i=1;i<=n;i++){
		if(!f[i]){
			if(!f[a.fa[i]])g.add(i,a.fa[i]);
			if(!f[b.fa[i]])g.add(b.fa[i],i);
			cnt++;
		}
	}
	for(i=1;i<=n;i++){
		if(!g.dfs(i))return inf;
	}
	return cnt;
}
void work(){
	int i,j,x,y,ans;
	scanf("%d",&n);
	a.reset();
	b.reset();
	memset(d,0,sizeof(d));
	for(i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		a.add(x,y);
		a.add(y,x);
		d[x]++;
		d[y]++;
	}
	for(i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		b.add(x,y);
		b.add(y,x);
	}
	ans=inf;
	for(i=1;i<=n;i++)ans=min(ans,solve(i));
	for(i=1;i<=n;i++){
		if(d[i]==1){
			for(j=1;j<=n;j++){
				if(j!=i){
					x=a.to[a.h[i]];
					a.to[a.h[i]]=j;
					ans=min(ans,solve(i)+1);
					a.to[a.h[i]]=x;
				}
			}
		}
	}
	if(ans==inf)ans=-1;
	printf("%d\n",ans);
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--)work();
}

[AGC027F]Grafting的更多相关文章

  1. POJ 3437 Tree Grafting

    题意:给出一个深度优先遍历树的up down顺序,求这棵树以及这棵树变为”左子右兄”树的高度 思路:直接dfs,x代表树1的高度,y代表树2的高度 #include<cstdio> #in ...

  2. web server && web framework角色区分

    问题 web framework是否包括webserver? 是否可以包括? webserver 和 framework的关系是? https://www.quora.com/What-is-the- ...

  3. HOJ题目分类

    各种杂题,水题,模拟,包括简单数论. 1001 A+B 1002 A+B+C 1009 Fat Cat 1010 The Angle 1011 Unix ls 1012 Decoding Task 1 ...

  4. 【Rice】Cultivar versus Variety

    From Cindy Haynes, Department of Horticulture   As a horticulturist, it is important that I use the ...

  5. TED_Topic10:The case for engineering our food

    By Pamela Ronald Pamela Ronald studies the genes that make plants more resistant to disease and stre ...

  6. 【Atcoder】AGC027 题解

    A - Candy Distribution Again 大意:有x个糖给n个小朋友,必须分完,小朋友得到糖数为一个确切值的时候小朋友会开心,求最多的开心数 题解 直接排序然后贪心分,如果分到最后一个 ...

  7. SPOJ:Ada and Graft (set合并&优化)

    As you might already know, Ada the Ladybug is a farmer. She grows a big fruit tree (with root in 0). ...

  8. CVPR 2020 全部论文 分类汇总和打包下载

    CVPR 2020 共收录 1470篇文章,根据当前的公布情况,人工智能学社整理了以下约100篇,分享给读者. 代码开源情况:详见每篇注释,当前共15篇开源.(持续更新中,可关注了解). 算法主要领域 ...

  9. CVPR 2020论文收藏(转知乎:https://zhuanlan.zhihu.com/p/112337176)

    CVPR 2020 共收录 1470篇文章,根据当前的公布情况,人工智能学社整理了以下约100篇,分享给读者. 代码开源情况:详见每篇注释,当前共15篇开源.(持续更新中,可关注了解). 算法主要领域 ...

随机推荐

  1. HDU 2639 Bone Collector II (dp)

    题目链接 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took part in ...

  2. ES6新用法

    ES6 详细参考页面 简介 ECMAScript和JavaScript的关系是,前者是后者的规格,后者是前者的一种实现.一般来说,这两个词是可以互换的. let命令 ES6新增了let命令,用来声明变 ...

  3. Tomcat的安装以及基本配置

    Tomcat是目前最常见也是最流行的基于java的一个web服务器软件   Tomcat的安装   (1)首先需要java环境,也就是说要依赖于java虚拟机JVM   (2)下载Tomcat ,地址 ...

  4. 理解js中私有变量

    私有变量在js中是个什么概念.当下我的认识是var所定义的变量,实际可以理解为属性和方法,或者单单是临时存储器,不归属任何对象. 一个声明函数: function a(){  var v = &quo ...

  5. GDB实战

    程序中除了一目了然的Bug之外都需要一定的调试手段来分析到底错在哪.到目前为止我们的调试手段只有一种:根据程序执行时的出错现象假设错误原因,然后在代码中适当的位置插入 printf ,执行程序并分析打 ...

  6. ZZ:Solaris 10 软件包分析

    ZZ:Solaris 10 软件包分析 http://blog.chinaunix.net/uid-22759617-id-276756.html # Last updated: 2006-02-14 ...

  7. PhysX SDK

    PhysX SDK https://developer.nvidia.com/physx-sdk NVIDIA PhysX SDK Downloads http://www.nvidia.cn/obj ...

  8. 【数位dp入门】【HDU4734】F(x)

    记录减的状态,表示还要凑多少才能达到当前值. 然后进行枚举即可.注意状态数不能重复. #include<bits/stdc++.h> #define N 10010 using names ...

  9. ASPxgridview 编辑列初始化事件

    在初始化编辑咧的时候,给其赋值或者是disable等等.... 贴上代码 protected void master_CellEditorInitialize(object sender, ASPxG ...

  10. 虚拟机 VMware Workstation12 安装Ubuntu系统

    Ubuntu 系统是一款优秀的.基于GNU/Linux 的平台的桌面系统. 当然,目前为止很多应用程序还完全不能允许运行在 Ubuntu 系统上,而且 Ubuntu 的界面.使用方法会让大部分Wind ...