【P2634】聪聪可可——点分治
(题面来自Luogu)
题目描述
聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃、两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已经玩儿腻了这种低智商的游戏。
他们的爸爸快被他们的争吵烦死了,所以他发明了一个新游戏:由爸爸在纸上画n个“点”,并用n-1条“边”把这n个“点”恰好连通(其实这就是一棵树)。并且每条“边”上都有一个数。接下来由聪聪和可可分别随即选一个点(当然他们选点时是看不到这棵树的),如果两个点之间所有边上数的和加起来恰好是3的倍数,则判聪聪赢,否则可可赢。
聪聪非常爱思考问题,在每次游戏后都会仔细研究这棵树,希望知道对于这张图自己的获胜概率是多少。现请你帮忙求出这个值以验证聪聪的答案是否正确。
输入输出格式
输入格式:
输入的第1行包含1个正整数n。后面n-1行,每行3个整数x、y、w,表示x号点和y号点之间有一条边,上面的数是w。
输出格式:
以即约分数形式输出这个概率(即“a/b”的形式,其中a和b必须互质。如果概率为1,输出“1/1”)。
用点分治统计从每个点u出发的路径,在cnt[k]中计数;其中k属于{0, 1, 2},表示该数组统计通过当前节点的长度%3等于k的路径数目。考虑将这些节点两两组合成长度%3等于0的路径:cnt[1]可以与cnt[2]两两组合,且题中给定的是有序点对,那么通过点u的满足条件的路径数ret += (cnt[2] * cnt[1] * 2)。cnt[0]可以两两组合,且可以重复,则ret += cnt[0] * cnt[0]。
代码:
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <cctype>
- #define BUG puts("$$$")
- #define maxn 20010
- using namespace std;
- const int inf = 0x3f3f3f3f;
- int n;
- template <typename T>
- void read(T &x) {
- x = 0;
- char ch = getchar();
- int f = 1;
- while (!isdigit(ch)) {
- if (ch == '-') f = -1;
- ch = getchar();
- }
- while (isdigit(ch)) {
- x = x * 10 + (ch ^ 48);
- ch = getchar();
- }
- x *= f;
- }
- long long gcd(long long a, long long b) {
- if (!b) return a;
- return gcd(b, a % b);
- }
- int head[maxn], top;
- struct E {
- int to, nxt, w;
- } edge[maxn << 1];
- inline void insert(int u, int v, int w) {
- edge[++top] = (E) {v, head[u], w};
- head[u] = top;
- }
- int cnt[3];
- int size[maxn], Size, mn, root;
- bool vis[maxn];
- void find_rt(int u, int pre) {
- size[u] = 1;
- int son = 0;
- for (int i = head[u]; i; i = edge[i].nxt) {
- int v = edge[i].to;
- if (v == pre || vis[v]) continue;
- find_rt(v, u);
- size[u] += size[v];
- if (size[v] > size[son]) son = v;
- }
- int cur = max(size[son], Size - size[u]);
- if (cur < mn)
- mn = cur, root = u;
- }
- void dfs(int u, int pre, int depth, int val) {
- cnt[depth % 3] += val;
- for (int i = head[u]; i; i = edge[i].nxt) {
- int v = edge[i].to;
- if (v == pre || vis[v]) continue;
- dfs(v, u, depth + edge[i].w, val);
- }
- }
- long long solve(int u, int extra) {
- dfs(u, 0, extra, 1);
- long long ret = 1LL * cnt[1] * cnt[2] * 2 + 1LL * cnt[0] * cnt[0];
- dfs(u, 0, extra, -1);
- return ret;
- }
- long long ans;
- void divide(int u) {
- vis[u] = true;
- ans += solve(u, 0);
- int curSize = Size;
- for (int i = head[u]; i; i = edge[i].nxt) {
- int v = edge[i].to;
- if (vis[v]) continue;
- ans -= solve(v, edge[i].w);
- mn = inf, Size = size[u] > size[v] ? size[v] : curSize - size[u];
- find_rt(v, u);
- divide(root);
- }
- }
- int main() {
- read(n);
- int u, v, w;
- for (int i = 1; i < n; ++i) {
- read(u), read(v), read(w);
- insert(u, v, w), insert(v, u, w);
- }
- mn = inf, Size = n;
- find_rt(1, 0);
- divide(root);
- long long down = 1LL * n * n, k = gcd(down, ans);
- printf("%lld/%lld", ans / k, down / k);
- return 0;
- }
【P2634】聪聪可可——点分治的更多相关文章
- [bzoj2152][聪聪和可可] (点分治+概率)
Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...
- bzoj2152 / P2634 [国家集训队]聪聪可可(点分治)
P2634 [国家集训队]聪聪可可 淀粉质点分治板子 边权直接 mod 3 直接点分治统计出所有的符合条件的点对再和总方案数约分 至于约分.....gcd搞搞就好辣 #include<iostr ...
- 洛谷 P2634 [国家集训队]聪聪可可-树分治(点分治,容斥版) +读入挂+手动O2优化吸点氧才过。。。-树上路径为3的倍数的路径数量
P2634 [国家集训队]聪聪可可 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一 ...
- P2634 [国家集训队]聪聪可可(题解)(点分治)
P2634 [国家集训队]聪聪可可(题解)(点分治) 洛谷题目 #include<iostream> #include<cstdlib> #include<cstdio& ...
- 模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)
洛谷P2634 [国家集训队]聪聪可可 静态点分治 一开始还以为要把分治树建出来……• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法.• A:朴素做法,直接找重心, ...
- AC日记——【模板】点分治(聪聪可可) 洛谷 P2634
[模板]点分治(聪聪可可) 思路: 点分治: (感谢灯神) 代码: #include <bits/stdc++.h> using namespace std; #define maxn 2 ...
- 洛谷-P2634 [国家集训队]聪聪可可 点分治
Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...
- 洛谷P2634 [国家集训队]聪聪可可 (点分治)
题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已 ...
- 洛谷 P2634 BZOJ 2152 【模板】点分治(聪聪可可)
题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已 ...
随机推荐
- 一起学Vue:入门
Why-为什么需要Vue? 前端开发存在的问题? 其一,需求变化频率更高 产品功能迭代前端肯定需要跟着调整. 提意见的人多,前端嘛谁都能看得见,所以,谁都可以指手画脚提一点意见.产品经理.项目经理.老 ...
- IDEA上运行Flink任务
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Flask 中的MTV架构之Models
Flask 中的MTV架构之Models 1.Models(数据模型) 1.1 flask-sqlalchemy(数据库) 说明:提供了大多数关系型数据库的支持,而且提供了ORM # 安装: pi ...
- leetcode111:combination-sum
题目描述 给出一组候选数C和一个目标数T,找出候选数中加起来和等于T的所有组合. C中的数字在组合中可以被无限次使用 注意: 题目中所有的数字(包括目标数T)都是正整数 你给出的组合中的数字 (a 1 ...
- Tensorflow学习---argmax中axis问题
一:argmax中axis问题 https://blog.csdn.net/qq575379110/article/details/70538051/ 总之:axis=0/1不是行/列关系 test ...
- 百度开源插件echarts介绍及如何使用
前言 如果你想要用较少的代码实现比较酷炫的数据统计表,echarts是值得你考虑的一种实现方式.官网提供了很多实例供参考:http://echarts.baidu.com/examples.html. ...
- 02模板渲染和参数(补充:URL传参到视图)
先抛出代码: @app.route('/') def index(): return render_template('index.html',username ="郑勇") 问题 ...
- Golang调度器GMP原理与调度全分析(转 侵 删)
该文章主要详细具体的介绍Goroutine调度器过程及原理,包括如下几个章节. 第一章 Golang调度器的由来 第二章 Goroutine调度器的GMP模型及设计思想 第三章 Goroutine调度 ...
- UNIX系统编程:文件IO(I)
1.标准C库中访问文件用的是文件指针FILE *(stdin,stdout,stderr):对于linux系统编程而言,所有对设备或文件的操作都是通过文件描述符进行的 2.当打开或者创建一个文件的时候 ...
- debian修改crontab默认编辑器为vim
debian终端下默认编辑器为nano,比如crontab -e就会打开nano,这个编辑器用起来很不习惯,想修改为vim,当然,你的debian系统必须先安装vim.如果已经安装vim,请输入如下命 ...