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

如果答案不是$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. MSSQL数据库 事务隔离级别

    数据库事务的隔离级别有4个,由低到高依次为Read uncommitted .Read committed .Repeatable read .Serializable ,这四个级别可以逐个解 脏读 ...

  2. libSVM笔记之(一)在matlab环境下安装配置libSVM

    本文为原创作品,转载请注明出处 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和http://www.cnblogs.com/xujianqing 台湾林智仁教 ...

  3. 移动测试===利用adb命令查看apk文件包名的一些方法

    前提是已经下载android SDK并配好环境变量! 在控制台输入命令$adb shell pm 可以看到adb shell pm的相关用法,详细信息请自己看输出 要看一个apk文件的相关信息最简单实 ...

  4. gradle问题总结与理解(一篇文章带你理解android studio 与gradle 的关系)

    前言:近日在网上找了个很不错的安卓二维码美化,由于下载的项目经常出问题,且不方便依赖使用,因此我想把它写个demo,并把源码发布到jcenter中,修改还是很顺利的,运行项目到手机也没问题,发布遇到了 ...

  5. sicily 1063. Who's the Boss

    Time Limit: 1sec    Memory Limit:32MB  Description Several surveys indicate that the taller you are, ...

  6. 【转载】 ftp 命令行

    原文在这里. 本文中,介绍在 Linux shell 中如何使用 ftp 命令.包括如何连接 FTP 服务器,上传或下载文件以及创建文件夹.尽管现在有许多不错的 FTP 桌面应用,但是在服务器.SSH ...

  7. centos安装更新Python2.7以及pip的安装

    一.首先对相关的软件进行更新 python -V yum -y update yum groupinstall -y development yum install -y zlib zlib-dev ...

  8. 利用ncurses库开发终端工具箱(1)—— ToDoList小工具开发

    准备工作 腾讯云服务器(Ubuntu),C++编程语言 由于想输出界面中包含中文,所以安装库 libncursesw5,依次输入下面三行命令 sudo apt-get install libncurs ...

  9. Sql Server中常用函数replicate

    SQL常用函数之三 REPLICATE () 按指定次数重复字符表达式. 语法 REPLICATE ( character_expression, integer_expression) 参数 cha ...

  10. NET应用——你的数据安全有必要升级

    最近又被[现场破解共享单车系统]刷了一脸,不得不开始后怕:如何防止类似的情况发生? 想来想去,始终觉得将程序加密是最简单的做法.但是摩拜.ofo也有加密,为什么仍然被破解?那是因为请求在传输过程中被篡 ...