Codeforces GYM 101968 A. Tree Game
差点自闭,感谢大佬帮忙找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的更多相关文章
- Codeforces 461B Appleman and Tree(木dp)
题目链接:Codeforces 461B Appleman and Tree 题目大意:一棵树,以0节点为根节点,给定每一个节点的父亲节点,以及每一个点的颜色(0表示白色,1表示黑色),切断这棵树的k ...
- Codeforces Gym 101252D&&floyd判圈算法学习笔记
一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...
- Codeforces Gym 101190M Mole Tunnels - 费用流
题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\rig ...
- Codeforces Gym 101623A - 动态规划
题目传送门 传送门 题目大意 给定一个长度为$n$的序列,要求划分成最少的段数,然后将这些段排序使得新序列单调不减. 考虑将相邻的相等的数缩成一个数. 假设没有分成了$n$段,考虑最少能够减少多少划分 ...
- 【Codeforces Gym 100725K】Key Insertion
Codeforces Gym 100725K 题意:给定一个初始全0的序列,然后给\(n\)个查询,每一次调用\(Insert(L_i,i)\),其中\(Insert(L,K)\)表示在第L位插入K, ...
- 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 ...
- Codeforces 1129 E.Legendary Tree
Codeforces 1129 E.Legendary Tree 解题思路: 这题好厉害,我来复读一下官方题解,顺便补充几句. 首先,可以通过询问 \(n-1\) 次 \((S=\{1\},T=\{ ...
- Codeforces 280C Game on tree【概率DP】
Codeforces 280C Game on tree LINK 题目大意:给你一棵树,1号节点是根,每次等概率选择没有被染黑的一个节点染黑其所有子树中的节点,问染黑所有节点的期望次数 #inclu ...
- codeforces gym 100553I
codeforces gym 100553I solution 令a[i]表示位置i的船的编号 研究可以发现,应是从中间开始,往两边跳.... 于是就是一个点往两边的最长下降子序列之和减一 魔改树状数 ...
随机推荐
- [uva11806]容斥定理
n*m的矩形 k个人 第一行,最后一行,第一列,最后一列都至少站有一个人 小水题 正着做不好做,要反着想,那就容斥定理,ABCD四种情况分别是那四个行列分别没有人. #include<cstdi ...
- performSelector支持多参数
默认的performSelector支持最多传递两个参数,要想传递超过两个的参数,需要使用NSInvocation来模拟performSelector的行为,如下: - (id)performSele ...
- 打印菱形(c语言)
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main() { // 定 ...
- HDU 2199 二分
我们可以发现这个函数是单增的,那么这样二分就好了. 反思:刚转C++,不会用scanf读入实数.(scanf("%lf",&y)) //By BLADEVIL #inclu ...
- js基础知识点收集
js基础知识点收集 js常用基本类型 function show(x) { console.log(typeof(x)); // undefined console.log(typeof(10)); ...
- pandas中DataFrame使用
切片选择 #显示第一行数据print(df.head(1)) #显示倒数三行数据 print(df.tail(3)) loc df.loc[row_index,col_index] 注意loc是根 ...
- [转]python os模块 常用命令
python编程时,经常和文件.目录打交道,这是就离不了os模块.os模块包含普遍的操作系统功能,与具体的平台无关.以下列举常用的命令 1. os.name()——判断现在正在实用的平台,Window ...
- dev_cpu_dead
Kernel: 4.12.6 每个cpu都有自己的softnet_data结构,用来处理数据包接收,但是当softnet_data所在cpu无法工作时,即CPUHP_NET_DEV_DEAD状态,就需 ...
- Linux Platform驱动模型(二) _驱动方法【转】
转自:http://www.cnblogs.com/xiaojiang1025/archive/2017/02/06/6367910.html 在Linux设备树语法详解和Linux Platform ...
- python基础===如何优雅的写代码(转自网络)
本文是Raymond Hettinger在2013年美国PyCon演讲的笔记(视频, 幻灯片). 示例代码和引用的语录都来自Raymond的演讲.这是我按我的理解整理出来的,希望你们理解起来跟我一样顺 ...