差点自闭,感谢大佬帮忙找bug

题目:https://codeforces.com/gym/101968/problem/A

找树的重心+思维

找到树的重心,如果重心只有一个,以重心为根节点dfs,求各节点深度,那么任意一对节点都符合题意,只要让先手mark深度小的节点即可,其中同样深度的节点,交换位置扔符合题意,要加上dep[i]*(dep[i]-1)/2

如果重心有两个,分别以两个重心为根节点dfs,以任意一对节点都符合题意为基础(ans=n*(n-1)/2),如果两个深度相同的节点分别挂在两个不同的重心上,那么他们无法作为符合题意的一对节点,要减去这一部分,对每个重心深度相同的节点,分别加上交换节点扔符合题意的一部分,嗯就这样

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<set>
#include<stack>
#include<map>
#include<fstream>
#include<cstdlib>
#include<ctime>
#include<list>
#include<climits>
#include<bitset>
#include<random>
using namespace std;
#define fopen freopen("input.in", "r", stdin);freopen("output.in", "w", stdout);
#define left asfdasdasdfasdfsdfasfsdfasfdas1
#define right asfdasdasdfasdfsdfasfsdfasfdas2
#define y1 asfdasdasdfasdfsdfasfsdfasfdas3
typedef long long ll;
typedef unsigned ui;
typedef long double ld;
const int dell[][]={{,},{,-},{,},{,-},{-,},{-,-},{-,},{-,-}};
ll mod=1e9+;
const ll inf=(1LL<<)-;
const int maxn=1e6+;
const int maxm=1e6+;
const double eps=1e-;
const double pi=acos(-1.0);
const int csize=;
int n,k,m,ar[maxn];
struct node{
int b,nex;
}no[maxn*];
int head[maxn],sz,mx,root;
int pre[maxn];
ll sspre[maxn];
int pre2[maxn];
ll sspre2[maxn];
void init(){
for(int i=;i<=n;i++)head[i]=-;
sz=;
}
void add(int a,int b){
no[sz].b=b;
no[sz].nex=head[a];
head[a]=sz++;
}
int dep[maxn],num[maxn];
void dfs(int u,int fa)
{
num[u]=;
if(dep[u]>mx){
mx=dep[u];
root=u;
}
for(int i=head[u];i!=-;i=no[i].nex){
int v=no[i].b;
if(v==fa)continue;
dep[v]=dep[u]+;
dfs(v,u);
num[u] += num[v];
}
}
bool findmid(int u,int& mid){
bool can=;
for(int i=head[u];i!=-;i=no[i].nex){
int v=no[i].b;
if(dep[v]==dep[u]+){
if(findmid(v,mid)){
return ;
}
can &= num[v]<(n+)/;
}
}
if(can && num[u]>=(n+)/){
mid=u;
return ;
}
else return ;
} int main()
{
//fopen
//freopen("input.in","r",stdin);
int t;scanf("%d",&t);
while(t--){
scanf("%d",&n);
init();
for(int i=;i<=n;i++){
int x;scanf("%d",&x);
add(i,x);
add(x,i);
}
mx=;root=;
dep[]=;
dfs(,-);
int mid=;
findmid(,mid);
ll ans=1LL*n*(n-)/;
if(n%== && num[mid]==n/){
int mid2=;
for(int i=head[mid];i!=-;i=no[i].nex){
if(dep[no[i].b]+==dep[mid]){
mid2=no[i].b;
break;
}
}
for(int i=;i<=n;i++)dep[i]=;
dep[mid2]=;
dfs(mid2,mid);
for(int i=;i<=n+;i++)pre[i]=pre2[i]=;
for(int i=;i<=n;i++){
if(dep[i]>)pre2[dep[i]]++;
} for(int i=;i<=n;i++)dep[i]=;
dep[mid]=;
dfs(mid,mid2);
for(int i=;i<=n;i++){
if(dep[i]>){
pre[dep[i]]++;
}
}
for(int i=;i<=n;i++){
ans -= (ll)pre[i]*pre2[i];
}
for(int i=;i<=n;i++){
ans += (ll)pre[i]*(pre[i]-)/;
ans += (ll)pre2[i]*(pre2[i]-)/;
}
}
else{
//if(fir==1609)while(1);
dep[mid]=;
dfs(mid,-);
for(int i=;i<=n+;i++)pre[i]=;
for(int i=;i<=n;i++)pre[dep[i]]++;
for(int i=;i<=n;i++){
ans += (ll)pre[i]*(pre[i]-)/;
}
}
printf("%lld\n",ans);
}
return ;
}

Codeforces GYM 101968 A. Tree Game的更多相关文章

  1. Codeforces 461B Appleman and Tree(木dp)

    题目链接:Codeforces 461B Appleman and Tree 题目大意:一棵树,以0节点为根节点,给定每一个节点的父亲节点,以及每一个点的颜色(0表示白色,1表示黑色),切断这棵树的k ...

  2. Codeforces Gym 101252D&&floyd判圈算法学习笔记

    一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...

  3. Codeforces Gym 101190M Mole Tunnels - 费用流

    题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\rig ...

  4. Codeforces Gym 101623A - 动态规划

    题目传送门 传送门 题目大意 给定一个长度为$n$的序列,要求划分成最少的段数,然后将这些段排序使得新序列单调不减. 考虑将相邻的相等的数缩成一个数. 假设没有分成了$n$段,考虑最少能够减少多少划分 ...

  5. 【Codeforces Gym 100725K】Key Insertion

    Codeforces Gym 100725K 题意:给定一个初始全0的序列,然后给\(n\)个查询,每一次调用\(Insert(L_i,i)\),其中\(Insert(L,K)\)表示在第L位插入K, ...

  6. Codeforces gym 101343 J.Husam and the Broken Present 2【状压dp】

     2017 JUST Programming Contest 2.0 题目链接:Codeforces gym 101343 J.Husam and the Broken Present 2 J. Hu ...

  7. Codeforces 1129 E.Legendary Tree

    Codeforces 1129 E.Legendary Tree 解题思路: 这题好厉害,我来复读一下官方题解,顺便补充几句. 首先,可以通过询问 \(n-1​\) 次 \((S=\{1\},T=\{ ...

  8. Codeforces 280C Game on tree【概率DP】

    Codeforces 280C Game on tree LINK 题目大意:给你一棵树,1号节点是根,每次等概率选择没有被染黑的一个节点染黑其所有子树中的节点,问染黑所有节点的期望次数 #inclu ...

  9. codeforces gym 100553I

    codeforces gym 100553I solution 令a[i]表示位置i的船的编号 研究可以发现,应是从中间开始,往两边跳.... 于是就是一个点往两边的最长下降子序列之和减一 魔改树状数 ...

随机推荐

  1. 2017 济南综合班 Day 5

    毕业考试 (exam.cpp/c/pas) (1s/256M) 问题描述 快毕业了,Barry希望能通过期末的N门考试来顺利毕业.如果他的N门考试平均分能够达到V分,则他能够成功毕业.现在已知每门的分 ...

  2. bzoj 1914: [Usaco2010 OPen]Triangle Counting 数三角形——极角排序

    Description 在一只大灰狼偷偷潜入Farmer Don的牛群被群牛发现后,贝西现在不得不履行着她站岗的职责.从她的守卫塔向下瞭望简直就是一件烦透了的事情.她决定做一些开发智力的小练习,防止她 ...

  3. 【BZOJ】1718: [Usaco2006 Jan] Redundant Paths 分离的路径

    [题意]给定无向连通图,要求添加最少的边使全图变成边双连通分量. [算法]Tarjan缩点 [题解]首先边双缩点,得到一棵树(无向无环图). 入度为1的点就是叶子,两个LCA为根的叶子间合并最高效,直 ...

  4. 12.13记录//QQDemo示例程序源代码

            笔记的完整版pdf文档下载地址: https://www.evernote.com/shard/s227/sh/ac692160-68c7-4149-83ea-0db5385e28b0 ...

  5. python学习笔记(六)之操作符

    python中算术操作符: + - * / % ** // 注意: /:为真实除法,即对应数学中的除法,通常返回一个浮点数 //:取整除法,即取商 %:求模,即取余数 **:幂运算,这里需要注意的一点 ...

  6. 表格td内容超出宽度显示... table-layout: fixed;

    td宽度用百分比固定好的时候,即使设置了 white-space:nowrap;/*文本不会换行,在同一行显示*/ overflow:hidden;超出隐藏 text-overflow:ellipsi ...

  7. Sketch VS Photoshop

    参考:http://mp.weixin.qq.com/s?__biz=MjM5NTQ5MjIyMA==&mid=217309554&idx=4&sn=4d6a5239ca813 ...

  8. python作业三级菜单day1(第一周)

    一.作业需求: 1. 运行程序输出第一级菜单 2. 选择一级菜单某项,输出二级菜单,同理输出三级菜单 3. 菜单数据保存在文件中 4. 让用户选择是否要退出 5. 有返回上一级菜单的功能 二三级菜单文 ...

  9. 2012年Elsevier旗下Computer Science期刊最新SCI影响因子排名

    Latest Impact Factor figures from Elsevier's Computer Science Journals Medical Image Analysis Impact ...

  10. python实战===爬取所有微信好友的信息

    ''' 爬取所有T信好友的信息 ''' import itchat from pandas import DataFrame itchat.login() friends=itchat.get_fri ...