P2634 [国家集训队]聪聪可可(树上启发式合并)
生活随笔
收集整理的這篇文章主要介紹了
P2634 [国家集训队]聪聪可可(树上启发式合并)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
P2634 [國家集訓隊]聰聰可可(樹上啟發式合并)
題意:
一顆n個點的樹,問其中兩點之間的邊上數的和加起來是3的倍數的點對有多少個?
輸出這樣的點對所占比例
題解:
沒有修改,統計邊長為3的倍數,經典的樹上路徑統計,樹上啟發式請求一戰
但是調了一陣子沒調出來,我對dsu的理解還是不夠深,
代碼:
待修改代碼
#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; void read(){}; template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar) {x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...); } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef LOCALstartTime= clock();freopen("in.txt", "r", stdin); #endif } void Time_test() { #ifdef LOCALendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int maxn= 1e5 + 9; vector<PII> vec[maxn]; int sz[maxn]; int dis[maxn]; int son[maxn]; int Son; int num[3]; int ans= 0; void dfs_son(int u, int fa) {sz[u]= 1;for (auto it : vec[u]) {int v= it.first;int w= it.second;if (v == fa)continue;dis[u]= dis[fa] + w;dfs_son(v, u);sz[u]+= sz[v];if (sz[v] > sz[son[u]])son[u]= v;} } void cal(int u, int fa, int LCA) {int x= ((dis[LCA] - dis[u]) % 3 + 3) % 3;ans+= num[x];for (auto it : vec[u]) {int v= it.first;if (v != fa && v != son[u])cal(v, u, LCA);} } void add(int u, int fa, int val, int LCA) {int Dis= (dis[u] - dis[LCA]) % 3;num[Dis]+= val;for (auto it : vec[u]) {int v= it.first;if (v != fa && v != son[u])add(v, u, val, LCA);} } void work(int u, int fa, int keep) {for (auto it : vec[u]) {int v= it.first;if (v != fa && v != son[u])work(v, u, 0);}if (son[u]) {work(son[u], u, 1);Son= son[u];}add(u, fa, 1, u);Son= 0;cal(u, fa, u);if (!keep) {add(u, fa, -1, u);} } int main() {//rd_test();int n;read(n);for (int i= 1; i < n; i++) {int u, v, w;read(u, v, w);vec[u].push_back({v, w});vec[v].push_back({u, w});}dis[1]= 1;dfs_son(1, 0);work(1, 0, 1);ll a= ans + n;ll b= 1ll * n * n;ll g= __gcd(a, b);printf("%lld/%lld\n", a / g, b / g);//Time_test(); }洛谷上的AC代碼:
#include <bits/stdc++.h> using namespace std; #define For(pos) for (int k= First[pos]; k; k= Next[k]) const int Maxn= 2e4 + 5; int n, First[Maxn], to[Maxn * 2], Next[Maxn * 2], W[Maxn * 2], cnt; int son[Maxn], size[Maxn], deep[Maxn]; inline void add(int z, int y, int w) {Next[++cnt]= First[z];First[z]= cnt;to[cnt]= y;W[cnt]= w; } int ans= 0, P; inline int R() {char c;int sign= 1, res= 0;while ((c= getchar()) > '9' || c < '0')if (c == '-')sign= -1;res+= c - '0';while ((c= getchar()) >= '0' && c <= '9')res= res * 10 + c - '0';return res * sign; } void deal(int pos, int father) {size[pos]= 1;For(pos){if (to[k] == father)continue;deep[to[k]]= deep[pos] + W[k];deal(to[k], pos);size[pos]+= size[to[k]];if (size[son[pos]] < size[to[k]])son[pos]= to[k];} } int q[4];inline void cal(int pos, int LCA) {int x= (2 * deep[LCA] - deep[pos]) % 3 + 3;x= x % 3;ans+= q[x]; } void work(int pos, int father, bool ca, int LCA) {if (ca)cal(pos, LCA);elseq[deep[pos] % 3]++;For(pos){if (to[k] == father)continue;work(to[k], pos, ca, LCA);} } void dfs(int pos, int father, bool heavy) {For(pos) if (to[k] != father && to[k] != son[pos]){dfs(to[k], pos, 0);}if (son[pos])dfs(son[pos], pos, 1);For(pos){if (to[k] == father || to[k] == son[pos])continue;work(to[k], pos, 1, pos);work(to[k], pos, 0, pos);}cal(pos, pos);q[deep[pos] % 3]++;if (!heavy)q[0]= q[1]= q[2]= 0; } int main() {n= R();int a, b, w;for (int i= 1; i < n; i++) {a= R();b= R();w= R();add(a, b, w);add(b, a, w);}deal(1, 0);dfs(1, 0, 1);ans= ans * 2 + n;int di= n * n;for (int i= 2; i <= ans; i++)while (ans % i == 0 && di % i == 0) {ans/= i;di/= i;}if (ans == di)puts("1/1");elseprintf("%d/%d\n", ans, di); }總結
以上是生活随笔為你收集整理的P2634 [国家集训队]聪聪可可(树上启发式合并)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 孤岛飞鹰电视剧剧情 讲的是什么故事
- 下一篇: P3714 [BJOI2017]树的难题