洛谷 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& ...
随机推荐
- blog笔录1
(1)虚拟主机 (2)部署 部署完成后刷新页面会看到笑脸,在Home分组下控制器Application/Home/Controller/IndexController.class.php下定义显示 ( ...
- python bs4库
Beautiful Soup parses anything you give it, and does the tree traversal stuff for you. BeautifulSoup ...
- 51nod 1050 循环数组最大子段和【动态规划】
N个整数组成的循环序列a[1],a[2],a[3],-,a[n],求该序列如a[i]+a[i+1]+-+a[j]的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑a[n-1],a[n] ...
- PHP 锁机制
应用环境 解决高并发,库存为负数的情况 阻塞模式 如果其他进程已经加锁文件,当前进程会一直等其他进程解锁文件后继续执行 flock($fp, LOCK_EX) // 文件锁 非阻塞模式 如果其他进程已 ...
- 2014年武汉的IT行情好像不太好(续):20个月过后,再看当时面试过的几个公司--武汉财富基石-崩盘,辣妈萌宝-创业失败,朋友公司转交他人管理
2014年9月的时候,写过一篇面试的总结性质的文章,"2014年武汉的IT行情好像不太好". 原文地址:blog.csdn.net/fansunion/article/detai ...
- 轰炸III(codevs 1830)
题目背景 一个大小为N*M的城市遭到了X次轰炸,每次都炸了一个每条边都与边界平行的矩形. 题目描述 在轰炸后,有Y个关键点,指挥官想知道,它们有没有受到过轰炸,如果有,被炸了几次,最后一次是第几轮. ...
- 2102 石子归并 2codevs
2102 石子归并 2codevs 题目描述 Description 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为 ...
- Luca Canali
https://github.com/LucaCanali http://cern.ch/canali/
- RAC fail over 测试
oracle rac 11gr2中提供了多种 failover方式,这里只测试 server side TAF. 也就是说在server端配置的failover.这种配置方式的好处就是,如果有什么改动 ...
- java ee开发常用类和接口
1.javax.Validation接口,做mvc传入数据验证用 2.javax.servlet接口 3.javax.datasource接口 4.javax.session接口 5.javax.ht ...