[AGC027F]Grafting
题意:给定两棵树,一次操作形如:选一个未被选过的叶子,改变它的一条出边,问能否在第一棵树上做一些操作使得它变成第二棵树,如果能则询问最小操作次数
如果答案不是$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的更多相关文章
- POJ 3437 Tree Grafting
题意:给出一个深度优先遍历树的up down顺序,求这棵树以及这棵树变为”左子右兄”树的高度 思路:直接dfs,x代表树1的高度,y代表树2的高度 #include<cstdio> #in ...
- web server && web framework角色区分
问题 web framework是否包括webserver? 是否可以包括? webserver 和 framework的关系是? https://www.quora.com/What-is-the- ...
- HOJ题目分类
各种杂题,水题,模拟,包括简单数论. 1001 A+B 1002 A+B+C 1009 Fat Cat 1010 The Angle 1011 Unix ls 1012 Decoding Task 1 ...
- 【Rice】Cultivar versus Variety
From Cindy Haynes, Department of Horticulture As a horticulturist, it is important that I use the ...
- 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 ...
- 【Atcoder】AGC027 题解
A - Candy Distribution Again 大意:有x个糖给n个小朋友,必须分完,小朋友得到糖数为一个确切值的时候小朋友会开心,求最多的开心数 题解 直接排序然后贪心分,如果分到最后一个 ...
- 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). ...
- CVPR 2020 全部论文 分类汇总和打包下载
CVPR 2020 共收录 1470篇文章,根据当前的公布情况,人工智能学社整理了以下约100篇,分享给读者. 代码开源情况:详见每篇注释,当前共15篇开源.(持续更新中,可关注了解). 算法主要领域 ...
- CVPR 2020论文收藏(转知乎:https://zhuanlan.zhihu.com/p/112337176)
CVPR 2020 共收录 1470篇文章,根据当前的公布情况,人工智能学社整理了以下约100篇,分享给读者. 代码开源情况:详见每篇注释,当前共15篇开源.(持续更新中,可关注了解). 算法主要领域 ...
随机推荐
- HH实习 acm算法部 1689
题目描述 这学期到了十五周了,HH突然要去实训中心实习了,想到要拿着钳子,锯子什么的,头就有点大了,因为它挺好玩的,但是,也是很累的,看着学弟坐在机房悠闲地敲着代码,HH学长决定要让他们好好忙忙,这道 ...
- httpd -v command not found
使用 find / -name "apachectl"查找文件目录下执行 ./apachectl -v
- charles https抓包
1. 配置 Charles 根证书 首先打开 Charles: Charles 启动界面 主界面 然后如下图操作: 之后会弹出钥匙串,如果不弹出,请自行打开钥匙串,如下图: 钥匙串 系统默认是不信 ...
- 深入理解 JavaScript(四)
前言 Bob 大叔提出并发扬了 S.O.L.I.D 五大原则,用来更好地进行面向对象编程,五大原则分别是: The Single Responsibility Principle(单一职责 SRP) ...
- Linux中的vim实用命令 -- (转)
VI 有2个模式.我自己定义的 1. 命令模式,一开始进去的模式.一些指定的键盘输入会产生不同的效果 2. 输入模式,在命令模式下输入冒号(:) 就可以进入输入模式.按Esc键即可退出命令模式. ...
- 手把手教你写Linux设备驱动---中断(三)--workqueue实现(基于友善之臂4412开发板) 【转】
转自:http://blog.csdn.net/morixinguan/article/details/69680909 上节,我们讲到如何来实现tasklet小任务机制 http://blog.cs ...
- [Linux]Linux printf 输出重定向【转】
转自:http://www.cnblogs.com/aaronLinux/p/6765145.html?utm_source=itdadao&utm_medium=referral 方法一 # ...
- 打印 pmic register value
打印 PMIC register value 方式有二種, 一種是使用 adb shell cat pmic register 一種是直接在 code 裡 call dump pmic registe ...
- Call Mode feature
起源 user 在插著 充電器 打電話的狀況下, 為了安全起見, 避免 充電器在這時損害手機,間接造成 user 的傷害, 而有了這 feature, 在 battery voltage Vbat & ...
- centos_7.1.1503_src_2
farstream02-0.2.3-3.el7.src.rpm 05-Jul-2014 12:59 1.2M fcoe-utils-1.0.29-9.el7.src.rpm 31-Mar-2015 ...