NOI模拟 捉迷藏
1.NOIP模拟 排序2.NFLS 231031 比赛总结3.JOI2013Final/LOJ2763 现代豪宅4.省选模拟 序列5.省选模拟 过路费6.NOI模拟 序列7.NOI模拟 大战波特8.NOI模拟 Mizuki 与进化9.NOI模拟 刀客球10.NOI模拟 真夏は誰のモノ11.NOI模拟 树数术12.NOI模拟 序列13.NOI模拟 GCD14.NOI模拟 开关15.NOI模拟 排序幻觉16.NOI模拟 UTF-8
17.NOI模拟 捉迷藏
18.退背包简介/NOI模拟 卖画19.CSP模拟 取模20.CSP模拟 矩阵操作21.AGC007F Shik and Copying String22.洛谷P10336 [UESTCPC 2024] 2-聚类算法23.NFLS 241014 比赛总结24.QOJ5173 染色25.洛谷P11183 [ROIR 2018 Day2] 大数据处理涉及知识点:博弈论
题意
在一个树上,A 和 B 可以通过边在节点间移动,每回合可以不移动,或者移动到有边直接连接的节点。A 在抓 B,当 A 与 B 处于同一个节点时即为被抓住,可以发现无论如何 B 最后都会被抓住,你需要添加最小数量的边使得 B 有策略可以永远不会被抓住。
思路
最终的必败态是 A 和 B 处于同一个节点的情况,因此向前推一步,必败态为 B 能走到的节点距离 A 都小于等于 的情况,我们可以发现这样的节点是原树上的叶子节点,因此我们需要添加的边就是把叶子节点和树上某个点连起来,形成一个环,并且环长还不能小于等于 ,发现只要不是菊花图就一定有合法的添边方案。
现在考虑怎么使得添加的边数量最小——每个叶子都要连边,那么让叶子之间互相连边不就可以最小?但是不要忘了还有一个限制,即连出来的环长不能小于等于 ,可以证明只要不是同父亲的兄弟叶子节点连边,连出来的环长一定大于等于 。因此这件事就解决了,我们先让同父亲的叶子节点和别的叶子连边,其他的之间随便连就行。在计算的时候可以进一步简化,因为我们不关心具体的连边方案,只要不存在某个节点的儿子叶子节点个数超过所有节点数的一半,添边数仍为 ;否则为这个节点的儿子叶子节点个数。
代码
#include<bits/stdc++.h>
using namespace std;
template<class T>inline void rd(T &x){
T res=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while('0'<=ch && ch<='9'){res=res*10+ch-'0';ch=getchar();}
x=res*f;
}
template<class T>inline void wt(T x,char endch='\0'){
static char wtbuff[20];
static int wtptr;
if(x==0){
putchar('0');
}
else{
if(x<0){x=-x;putchar('-');}
wtptr=0;
while(x){wtbuff[wtptr++]=x%10+'0';x/=10;}
while(wtptr--) putchar(wtbuff[wtptr]);
}
if(endch!='\0') putchar(endch);
}
const int MAXN=1e5+5;
int n,de,deg[MAXN],fa[MAXN],leafcnt[MAXN],leaftot;
bool vis[MAXN];
inline void solve(){
rd(n);
de=0;leaftot=0;
fill(deg,deg+1+n,0);
fill(vis,vis+1+n,0);
fill(leafcnt,leafcnt+1+n,0);
for(int i=1,u,v;i<n;i++){
rd(u);rd(v);
deg[u]++;deg[v]++;
fa[u]=v;fa[v]=u;
}
if(n<=3){puts("-1");return;}
for(int i=1;i<=n;i++){
if(deg[i]==1) leafcnt[fa[i]]++,leaftot++;
}
int leafcntmax=-1;
for(int i=1;i<=n;i++){
if(leaftot==leafcnt[i]){
puts("-1");
return;
}
leafcntmax=max(leafcntmax,leafcnt[i]);
}
if(leafcntmax*2>=leaftot) wt(leafcntmax,'\n');
else wt((leaftot+1)/2,'\n');
}
int main(){
// freopen("hide.in","r",stdin);
// freopen("hide.out","w",stdout);
int t;
rd(t);
while(t--) solve();
return 0;
}
本文作者:MessageBoxA
本文链接:https://www.cnblogs.com/SkyNet-PKN/p/18228680
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步