日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

北京理工大学小学期乐学 t23树上统计

發布時間:2023/12/2 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 北京理工大学小学期乐学 t23树上统计 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寫在前頭

玩一下csdn的markdown。
這道題的大意是

給定一棵樹,兩個相鄰點之間的距離為111,對于相鄰距離為222的點之間可以新建一條邊,要求每個點到其他所有點點的距離之和的和。

看似是一道搜索題,但是我多日后再想起來感覺還有動態規劃的思路在里頭。

t23

參考帖子:http://lexue.bit.edu.cn/mod/forum/discuss.php?d=126124,閱讀前請先看一看這篇文章。

如果看不到原帖,這里大致概括本貼中用到的原帖中的結論,對于相鄰的節點 i,ji,ji,j,原帖總結了所有節點中除了 i,ji,ji,j 外的任意節點 xxxiii 的距離 ddd 于到 jjj 的距離 d′d'd 之間的關系。

本文是對上貼中最后留白部分的推論,我寫這個的時候程序還沒寫(主要是擔心寫不出ac,先寫寫推導過程拿一點平時分orz)

約定

在zzxdl的帖子中兩點之間的距離用 distdistdist 表示,文中用 ddd 表示,且 d(x,x)=0,d′(x,x)=0d(x,x)=0,d'(x,x)=0d(x,x)=0,d(x,x)=0

正文

對于圖 G(E,V)G(E,V)G(E,V),取一條邊 i?ji-ji?j,邊上的兩點分別為 i,ji,ji,j,設節點 iii 的所有子樹編號為 1,…,n1,\ldots,n1,,njjj 節點所有子樹編號為1,…,m1,\ldots,m1,,m,對于 iii 節點的第 kkk 個子樹上所有節點的集合為 SikS_{ik}Sik?,其中所有到 iii 距離為偶數的節點的集合為 EikE_{ik}Eik? ,距離為奇數的節點的集合為 OikO_{ik}Oik?。于節點 jjj 同理。

那么有:
?kEjk=?kOik?{j}?kOjk=?kEik∪{i}\begin{aligned} \bigcup_k{E_{jk}}=\bigcup_k{O_{ik}}-\{j\}\\ \bigcup_k{O_{jk}}=\bigcup_k{E_{ik}}\cup\{i\}\\ \end{aligned} k??Ejk?=k??Oik??{j}k??Ojk?=k??Eik?{i}?
令:
Oi=?kOikOj=?kOjkEi=?kEikEj=?kEjksumi=∑u≠id′(u,i)sumj=∑u≠jd′(u,j)\begin{aligned} &O_i=\bigcup_k{O_{ik}} & O_j=\bigcup_k{O_{jk}}\\ &E_i=\bigcup_k{E_{ik}} & E_j=\bigcup_k{E_{jk}}\\ &sum_i=\sum_{u\neq i}{d'(u,i)}\\&sum_j=\sum_{u\neq j}{d'(u,j)} \end{aligned} ?Oi?=k??Oik?Ei?=k??Eik?sumi?=u?=i?d(u,i)sumj?=u?=j?d(u,j)?Oj?=k??Ojk?Ej?=k??Ejk?
顯然,結合上文的推導:
sumi=∑u∈Eid′(u,i)+∑u∈Oid′(u,i)sumj=∑u∈Ejd′(u,j)+∑u∈Ojd′(u,j)=∑u∈Oi?{j}d′(u,j)+∑u∈Ei+{i}d′(u,j)=∑u∈Oid′(u,j)+∑u∈Eid′(u,j)+1\begin{aligned} sum_i&=\sum_{u\in E_i}{d'(u,i)}+\sum_{u\in O_i}{d'(u,i)}\\ sum_j&=\sum_{u\in E_j}{d'(u,j)}+\sum_{u\in O_j}{d'(u,j)}\\ &=\sum_{u\in O_i-\{j\}}{d'(u,j)}+\sum_{u\in E_i+\{i\}}{d'(u,j)}\\ &=\sum_{u\in O_i}{d'(u,j)}+\sum_{u\in E_i}{d'(u,j)}+1\\ \end{aligned} sumi?sumj??=uEi??d(u,i)+uOi??d(u,i)=uEj??d(u,j)+uOj??d(u,j)=uOi??{j}?d(u,j)+uEi?+{i}?d(u,j)=uOi??d(u,j)+uEi??d(u,j)+1?
由于 (i,j)∈E(i,j)\in E(i,j)E,所以有且僅有唯一的 p∈{1,2…,n}p\in\{1,2\ldots,n\}p{1,2,n},使得其所對應的子樹中所有點的集合滿足:
j∈SipEip+Oip=Sip\begin{aligned} j&\in S_{ip}\\ E_{ip}+O_{ip}&=S_{ip} \end{aligned} jEip?+Oip??Sip?=Sip??
那么:
sumj=∑u∈Oi?Oipd′(u,j)+∑u∈Ei?Eipd′(u,j)+1+∑u∈Oipd′(u,j)+∑u∈Eipd′(u,j)=∑u∈Oi?Oipd′(u,i)+∑u∈Ei?Eipd′(u,i)+1+∣Ei∣?∣Eip∣+∑u∈Oipd′(u,i)?∣Oip∣+∑u∈Eipd′(u,i)=∑u∈Eid′(u,i)+∑u∈Oid′(u,i)+∣Ei∣?∣Sip∣+1=sumi+∣Ei∣?∣Sip∣+1\begin{aligned} sum_j&=\sum_{u\in O_i-O_{ip}}{d'(u,j)}+\sum_{u\in E_i-E_{ip}}{d'(u,j)}+1+\sum_{u\in O_{ip}}{d'(u,j)}+\sum_{u\in E_{ip}}{d'(u,j)}\\ &=\sum_{u\in O_i-O_{ip}}{d'(u,i)}+\sum_{u\in E_i-E_{ip}}{d'(u,i)}+1+|E_i|-|E_{ip}|+\sum_{u\in O_{ip}}{d'(u,i)}-|O_{ip}|+\sum_{u\in E_{ip}}{d'(u,i)}\\ &=\sum_{u\in E_i}{d'(u,i)}+\sum_{u\in O_i}{d'(u,i)}+|E_i|-|S_{ip}|+1\\ &=sum_i+|E_i|-|S_{ip}|+1 \end{aligned} sumj??=uOi??Oip??d(u,j)+uEi??Eip??d(u,j)+1+uOip??d(u,j)+uEip??d(u,j)=uOi??Oip??d(u,i)+uEi??Eip??d(u,i)+1+Ei??Eip?+uOip??d(u,i)?Oip?+uEip??d(u,i)=uEi??d(u,i)+uOi??d(u,i)+Ei??Sip?+1=sumi?+Ei??Sip?+1?

由此再進行一次深度優先搜索即可得到答案。

貼上代碼

#include <iostream> #include <vector> using namespace std;#define N 200 // 2000000 #define HALF(x) (((x)&1) + ((x)>>1)) // 除二并向上取整vector<int> edge[N]; /* oddR 所有節點到根節點的奇數點的個數 evenR 所有節點到根節點的偶數點的個數 sizeTree 以r為根的數中每一個幾點所代表的子樹的節點個數 */ int oddR, evenR, sizeTree[N]; int disRoot[N]; // 節點到根的距離 long long sum[N], sumUp;int E(int i); // 到節點i的距離為偶數的點的個數 int O(int i); // 到節點i的距離為奇數的點的個數 int dfs1(int i, int f); // 給出所有點的子樹的規模 void dfs2(int i, int f, int r, int depth); // 給出所有點的奇偶節點的數量 void dfs3(int i, int f); // 轉移計算int main(void) {int n, a, b, r;cin >> n;while (n-- > 1){scanf("%d%d", &a, &b); getchar();edge[a].push_back(b);edge[b].push_back(a);}r = a;dfs1(r, 0);dfs2(r, 0, r, 1);sumUp += sum[r];dfs3(r, 0);cout << sumUp / 2 << endl;return 0; }void dfs3(int i, int f) {for (int j = 0; j < edge[i].size(); j++){int tmp = edge[i][j];if (tmp != f){sum[tmp] = sum[i] + E(i) - sizeTree[tmp] + 1;sumUp += sum[tmp];dfs3(tmp, i);}}return; }int E(int i) { return disRoot[i] % 2 == 0 ? evenR : oddR - 1; } int O(int i) { return disRoot[i] % 2 == 0 ? oddR : evenR + 1; }void dfs2(int i, int f, int r, int depth) {for (int j = 0; j < edge[i].size(); j++){int tmp = edge[i][j];if (tmp != f){if (depth & 1 == 1) // 距離根節點奇數距離oddR++;else evenR++; // 距離根節點偶數距離disRoot[tmp] = depth;sum[r] += HALF(depth);dfs2(tmp, i, r, depth + 1);}}return; }int dfs1(int i, int f) {for (int j = 0; j < edge[i].size(); j++){int tmp = edge[i][j];if (tmp != f)sizeTree[i] += dfs1(tmp, i);}sizeTree[i]++;return sizeTree[i]; }

總結

以上是生活随笔為你收集整理的北京理工大学小学期乐学 t23树上统计的全部內容,希望文章能夠幫你解決所遇到的問題。

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