博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NOIP2016模拟赛三 Problem C: 不虚就是要AK
阅读量:4958 次
发布时间:2019-06-12

本文共 2625 字,大约阅读时间需要 8 分钟。

题目大意

给定一棵带有边权的树, 问你在树上随机选两个点, 它们最短路径上的边权之和为\(4\)的倍数的概率为多少.

Solution

树分治. 没什么好讲的.

#include 
#include
#include
#include
#include
using namespace std;namespace Zeonfai{ inline int getInt() { int a = 0, sgn = 1; char c; while(! isdigit(c = getchar())) if(c == '-') sgn *= -1; while(isdigit(c)) a = a * 10 + c - '0', c = getchar(); return a * sgn; }}const int N = (int)2e4;int n;int cnt[4];long long ans;struct tree{ struct edge { int v, w; inline edge(int _v, int _w) {v = _v; w = _w;} }; struct node { vector
edg; int vst, sz, mx; inline node() {vst = 0; edg.clear();} }nd[N + 1]; inline void initialize() {for(int i = 1; i <= n; ++ i) nd[i] = node();} inline void addEdge(int u, int v, int w) {nd[u].edg.push_back(edge(v, w)); nd[v].edg.push_back(edge(u, w));} void getSize(int u, int pre) { nd[u].sz = 1; nd[u].mx = 0; for(auto edg : nd[u].edg) if(edg.v != pre && ! nd[edg.v].vst) getSize(edg.v, u), nd[u].sz += nd[edg.v].sz, nd[u].mx = max(nd[u].mx, nd[edg.v].sz); } int getRoot(int u, int pre, int cen) { nd[u].mx = max(nd[u].mx, nd[cen].sz - nd[u].sz); int res = u; for(auto edg : nd[u].edg) if(edg.v != pre && ! nd[edg.v].vst) { int cur = getRoot(edg.v, u, cen); if(nd[cur].mx < nd[res].mx) res = cur; } return res; } void getAnswer(int u, int pre, long long len) { ans += cnt[(4 - len % 4) % 4] << 1; for(auto edg : nd[u].edg) if(edg.v != pre && ! nd[edg.v].vst) getAnswer(edg.v, u, len + edg.w); } void update(int u, int pre, long long len) { ++ cnt[len % 4]; for(auto edg : nd[u].edg) if(edg.v != pre && ! nd[edg.v].vst) update(edg.v, u, len + edg.w); } inline void work(int u) { getSize(u, -1); u = getRoot(u, -1, u); memset(cnt, 0, sizeof(cnt)); cnt[0] = 1; ans += 1; for(auto edg : nd[u].edg) if(! nd[edg.v].vst) { getAnswer(edg.v, u, edg.w); update(edg.v, u, edg.w); } nd[u].vst = 1; for(auto edg : nd[u].edg) if(! nd[edg.v].vst) work(edg.v); } inline void work() {ans = 0; work(1);}}T;inline void output(long long a, long long b){ long long _a = a, _b = b; if(_a < _b) swap(_a, _b); while(_b) { long long tmp = _b; _b = _a % _b; _a = tmp; } printf("%lld/%lld\n", a / _a, b / _a);}int main(){#ifndef ONLINE_JUDGE freopen("AK.in", "r", stdin); freopen("AK.out", "w", stdout);#endif using namespace Zeonfai; while(n = getInt()) { T.initialize(); for(int i = 1, u, v, c; i < n; ++ i) u = getInt(), v = getInt(), c = getInt(), T.addEdge(u, v, c); T.work(); output(ans, (long long)n * n); }}

转载于:https://www.cnblogs.com/ZeonfaiHo/p/7519479.html

你可能感兴趣的文章
流操作的规律
查看>>
Python基础学习15--异常的分类与处理
查看>>
javascript运算符的优先级
查看>>
React + Redux 入门(一):抛开 React 学 Redux
查看>>
13位时间戳和时间格式化转换,工具类
查看>>
vue router-link子级返回父级页面
查看>>
C# 通知机制 IObserver<T> 和 IObservable<T>
查看>>
Code of Conduct by jsFoundation
查看>>
div 只显示两行超出部分隐藏
查看>>
C#小练习ⅲ
查看>>
电源防反接保护电路
查看>>
arraylist
查看>>
zoj 1649 Rescue (BFS)(转载)
查看>>
2124: 等差子序列 - BZOJ
查看>>
字符串匹配算法综述
查看>>
Linux centosVMware shell 管道符和作业控制、shell变量、环境变量配置文件
查看>>
【设计模式】工厂模式
查看>>
两个表格中数据不用是一一对应关系--来筛选不同数据,或者相同数据
查看>>
客户数据库出现大量cache buffer chains latch
查看>>
機械の総合病院 [MISSION LEVEL: C]
查看>>