洛谷 P2634 聪聪可可 —— 树形DP / 点分治
题目:https://www.luogu.org/problemnew/show/P2634
今天刚学了点分治,做例题;
好不容易A了,结果发现自己写的是树形DP...(也不用找重心)(比点分治快)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=,inf=0x3f3f3f3f;
int n,hd[maxn],ct,siz[maxn],mx,rt;
ll cnt[maxn][],ans,tot,tmp[];
struct N{
int to,nxt,w;
N(int t=,int n=,int w=):to(t),nxt(n),w(w) {}
}ed[maxn<<];
void add(int x,int y,int z){ed[++ct]=N(y,hd[x],z); hd[x]=ct;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void dfs(int x,int fa)
{
siz[x]=; int nmx=;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa)continue;
dfs(u,x); siz[x]+=siz[u];
nmx=max(nmx,siz[u]);
}
nmx=max(nmx,n-siz[x]);
if(nmx<mx)rt=x,mx=nmx;//mx=nmx!!
}
void work(int x,int fa)
{
cnt[x][]=;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa)continue;
work(u,x);
for(int j=;j<=;j++)tmp[j]=cnt[u][((j-ed[i].w)%+)%];
ans+=cnt[x][]*tmp[];
ans+=cnt[x][]*tmp[];
ans+=cnt[x][]*tmp[];
for(int j=;j<=;j++)cnt[x][j]+=tmp[j];
}
// ans+=cnt[x][0];//
// ans++;
}
int main()
{
// freopen("test.txt","r",stdin);
scanf("%d",&n); mx=inf;
for(int i=,x,y,z;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
dfs(,); work(rt,);
ans=ans*+n; tot=(ll)n*n;
ll g=gcd(ans,tot);
printf("%lld/%lld\n",ans/g,tot/g);
return ;
} 树形DP
树形DP
点分治是先算出经过根的,再去掉根,对于子树进行相同的操作,还要容斥掉刚才算上的、经过该子树根节点的答案。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=,inf=0x3f3f3f3f;
int n,hd[maxn],ct,siz[maxn],mx,rt,sum,dep[maxn];
ll cnt[maxn][],ans,tot,tmp[];
bool vis[maxn];
struct N{
int to,nxt,w;
N(int t=,int n=,int w=):to(t),nxt(n),w(w) {}
}ed[maxn<<];
void add(int x,int y,int z){ed[++ct]=N(y,hd[x],z); hd[x]=ct;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void dfs(int x,int fa)
{
siz[x]=; int nmx=;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa||vis[u])continue;
dfs(u,x); siz[x]+=siz[u];
nmx=max(nmx,siz[u]);
}
nmx=max(nmx,sum-siz[x]);
if(nmx<mx)rt=x,mx=nmx;//mx=nmx!!
}
void getdep(int x,int fa)
{
tmp[dep[x]%=]++;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa||vis[u])continue;
dep[u]=dep[x]+ed[i].w;
getdep(u,x);
}
}
ll calc(int x,int v)
{
dep[x]=v; tmp[]=tmp[]=tmp[]=;
getdep(x,);//0
return tmp[]*tmp[]+tmp[]*tmp[]*;
}
void work(int x)
{
ans+=calc(x,); vis[x]=;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if(vis[u=ed[i].to])continue;
ans-=calc(u,ed[i].w);
mx=inf; sum=siz[u]; dfs(u,);
work(rt);
}
}
int main()
{
// freopen("test.txt","r",stdin);
scanf("%d",&n);
for(int i=,x,y,z;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
mx=inf; sum=n; dfs(,); work(rt);
tot=(ll)n*n;
ll g=gcd(ans,tot);
printf("%lld/%lld\n",ans/g,tot/g);
return ;
}
洛谷 P2634 聪聪可可 —— 树形DP / 点分治的更多相关文章
- 洛谷 P3177 [HAOI2015]树上染色 树形DP
洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...
- 洛谷 P2634 BZOJ 2152 【模板】点分治(聪聪可可)
题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已 ...
- 洛谷P1040 加分二叉树(树形dp)
加分二叉树 时间限制: 1 Sec 内存限制: 125 MB提交: 11 解决: 7 题目描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,...,n),其中数字1,2,3,...,n ...
- 洛谷P4438 道路 [HNOI/AHOI2018] 树形dp
正解:树形dp 解题报告: 传送门! 昂首先看懂题目趴QwQ大概就是说有棵满二叉树,有n个叶子节点(乡村)和n-1个非叶子节点,然后这棵树的每个节点有三个属性abc,对每个非叶子节点可以从与子节点的两 ...
- 洛谷 P4201 设计路线 [NOI2008] 树形dp
正解:树形dp 解题报告: 大概是第一道NOI的题目?有点激动嘻嘻 然后先放个传送门 先大概港下这题的题意是啥qwq 大概就是给一棵树,然后可以选若干条链把链上的所有边的边权变成0,但是这些链不能有交 ...
- 洛谷 P3267 [JLOI2016/SHOI2016]侦察守卫(树形dp)
题面 luogu 题解 树形\(dp\) \(f[x][y]表示x的y层以下的所有点都已经覆盖完,还需要覆盖上面的y层的最小代价.\) \(g[x][y]表示x子树中所有点都已经覆盖完,并且x还能向上 ...
- 洛谷P1351 联合权值(树形dp)
题意 题目链接 Sol 一道很简单的树形dp,然而被我写的这么长 分别记录下距离为\(1/2\)的点数,权值和,最大值.以及相邻儿子之间的贡献. 树形dp一波.. #include<bits/s ...
- 洛谷P4099 [HEOI2013]SAO(树形dp)
传送门 HEOI的题好珂怕啊(各种意义上) 然后考虑树形dp,以大于为例 设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小有关,与实际数值无关) 我们考虑 ...
- 洛谷 P1351 联合权值 —— 树形DP
题目:https://www.luogu.org/problemnew/show/P1351 树形DP,别忘了子树之间的情况(拐一下距离为2). 代码如下: #include<iostream& ...
随机推荐
- svn无法显示日期和作者
当遇到这种情况,只要把这个read改为none就可以显示了 亲测绝对管用
- vim基础(一)
今天看了下兄弟连的VIM讲解,又学了几个新命令,记录一下. 插入与删除 插入 首先还是插入,以前只知道i.今天发现原来还有a\A\i\I\o\O,下面具体说一下: 命令 含义 a 在光标后插入 A 在 ...
- 如何卸载 win10 自带的“电影和电视”软件
参考这里: https://answers.microsoft.com/zh-hans/windows/forum/apps_windows_10-movies/win10%E7%9A%84%E7%9 ...
- 2014年武汉的IT行情好像不太好(续):20个月过后,再看当时面试过的几个公司--武汉财富基石-崩盘,辣妈萌宝-创业失败,朋友公司转交他人管理
2014年9月的时候,写过一篇面试的总结性质的文章,"2014年武汉的IT行情好像不太好". 原文地址:blog.csdn.net/fansunion/article/detai ...
- mysql根据用户的邀请码查询该用户所有的上级
SELECT T1.lvl AS 'level', T2.id AS 'id', T2.zid AS 'zid', T2.self_invite AS 'selfInvite', T2.invite_ ...
- 【Codeforces 584D】Dima and Lisa
[链接] 我是链接,点我呀:) [题意] 让你把一个奇数n分成最多个质数的和 [题解] 10的9次方以内,任意两个质数之间的差距最大为300 因此可以这样,我们先从i=n-2开始一直递减直到i变成最大 ...
- 九度oj 题目1050:完数
题目1050:完数 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8778 解决:3612 题目描述: 求1-n内的完数,所谓的完数是这样的数,它的所有因子相加等于它自身,比如6有3个因子 ...
- Linux下汇编语言学习笔记74 ---
这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...
- ORA-00604: 递归 SQL 级别 1 出现错误 ORA-01653: 表 SYS.AUD$ 无法通过 8192 (在表空间 SYSTEM 中) 扩展
https://blog.csdn.net/zhangyong329/article/details/53421951
- nyoj_278_排队_201403282135
排队 时间限制:3000 ms | 内存限制:65535 KB 难度:1 描述 周末了,软件ACM的队员准备玩玩游戏,娱乐一下,CY想了一个好主意,所有队员站成一个圈,从1开始报数,凡是报出指 ...