日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

mjt 树

發布時間:2024/10/12 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mjt 树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

\(mjt樹\)

題目背景

從前森林里有一棵很大的\(mjt\)樹,樹上有很多小動物。

題目描述

mjt樹上有 \(n\) 個房間,第 i 個房間住著\(a_i\) 只第bi 種小動物。
\(n\)個房間用\(n-1\)條路連接起來,其中房間1位\(mjt\)樹的根。
現在每個房間\(x\)的小動物想知道,以房間x為根的\(mjt\)樹中有多少只它們的同類.

輸入輸出格式

輸入格式:

第一行一個整數n,表示房間數
接下來\(n\)行,每行兩個整數\(a_i,b_i\)。
再之后\(n-1\)行,每行兩個整數\(x,y\),表示x和y之間有一條路徑

輸出格式:

一行n個數,第\(i\)個數表示以房間i為根的\(mjt\)樹中\(b_i\)種小動物有多少只,兩個數之間用空格隔開

輸入輸出樣例

輸入樣例#1:

5
2 1
3 1
4 2
5 1
6 2
1 2
1 3
3 4
3 5

輸出樣例#1:

10 3 10 5 6

說明

\(b_i\leq n\leq 100000,a_i\leq 1000\)
by xjjppm.

這個題好像是“理責慨”理叔出的
但是為什么叫“燜箭筒”樹我還真不知道

我YY了三個做法
有兩種做法能A這道題
首先題目將所有點劃分成許多種類
所以我用顏色代替

做法1:

DFS中找到每個點所有的與其顏色相同的所有祖先 在祖先中加上這個點的權值 缺陷:太慢

做法2:

將每個點的權值加到其最近的祖先處 然后在回溯的時候就會逐步加到其所有祖先處 查詢很快 如果整棵樹是比較均衡的樹 那么速度就會還不錯 缺陷:很容易被卡

做法3:

在DFS的時候處理正在遍歷的鏈上的所有顏色的節點 這樣就可以O(1)找出其最近祖先 同樣是將權值加到最近祖先處 速度和DFS遍歷樹的速度差不多 能非??焖俚耐ㄟ^該題

做法1

#include<iostream> #include<cstdio> #define N 1000005 using namespace std;struct node{int next,v; }edge[N]; int head[N],sum;void add(int a,int b){edge[++sum].v=b;edge[sum].next=head[a];head[a]=sum;edge[++sum].v=a;edge[sum].next=head[b];head[b]=sum; }int n; int fa[N]; int ans[N]; int zhong[N]; int duosh[N];int find(int s){int father=fa[s];while(father){ans[father]+=(zhong[s]==zhong[father])*duosh[s];father=fa[father];}ans[s]+=duosh[s]; }void DFS(int s,int fath){fa[s]=fath;find(s);for(int i=head[s];i;i=edge[i].next){if(edge[i].v==fa[s])continue;DFS(edge[i].v,s);} }int main(){cin>>n;for(int i=1;i<=n;++i)scanf("%d%d",&duosh[i],&zhong[i]);for(int i=1;i<n;++i){int a,b;scanf("%d%d",&a,&b);add(a,b);}DFS(1,0);for(int i=1;i<=n;++i)cout<<ans[i]<<' ';return 0; }

做法2

#include<iostream> #include<cstdio> #define N 200010 using namespace std;struct node{int next,v; }edge[N]; int head[N],sum;void add(int a,int b){edge[++sum].v=b;edge[sum].next=head[a];head[a]=sum;edge[++sum].v=a;edge[sum].next=head[b];head[b]=sum; }int n; int fa[N]; int ans[N]; int zhong[N]; int duosh[N];int find(int s){int father=fa[s];while(father){if(zhong[s]==zhong[father]){ans[father]+=ans[s];return 0;}father=fa[father];} }void DFS(int s,int fath){fa[s]=fath;for(int i=head[s];i;i=edge[i].next){if(edge[i].v==fa[s])continue;DFS(edge[i].v,s);}find(s); }int main(){scanf("%d",&n);for(int i=1;i<=n;++i)scanf("%d%d",&duosh[i],&zhong[i]);for(int i=1;i<n;++i){int a,b;scanf("%d%d",&a,&b);add(a,b);}for(int i=1;i<=n;++i)ans[i]=duosh[i];DFS(1,0);for(int i=1;i<=n;++i)printf("%d ",ans[i]);return 0; }

做法3

#include<iostream> #include<cstdio> #define N 1000010 using namespace std;struct node{int next,v; }edge[N]; int head[N],sum;void add(int a,int b){edge[++sum].v=b;edge[sum].next=head[a];head[a]=sum;edge[++sum].v=a;edge[sum].next=head[b];head[b]=sum; }int n; int fa[N]; int ans[N]; int zhong[N]; int duosh[N];int ff[N];//顏色為i的點最后一次出現的位置 int color[N];void DFS(int s,int fath){fa[s]=fath;int fn=ff[zhong[s]];ff[zhong[s]]=s;for(int i=head[s];i;i=edge[i].next){if(edge[i].v==fa[s])continue;DFS(edge[i].v,s);}ans[fn]+=ans[s];ff[zhong[s]]=fn; }int main(){scanf("%d",&n);for(int i=1;i<=n;++i)scanf("%d%d",&duosh[i],&zhong[i]);for(int i=1;i<n;++i){int a,b;scanf("%d%d",&a,&b);add(a,b);}for(int i=1;i<=n;++i)ans[i]=duosh[i];DFS(1,0);for(int i=1;i<=n;++i)printf("%d ",ans[i]);return 0; }

轉載于:https://www.cnblogs.com/qdscwyy/p/7739228.html

總結

以上是生活随笔為你收集整理的mjt 树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。