POJ 1741 Tree

Description

Give a tree with n vertices,each edge has a length(positive integer less than 1001).
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Input

The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
The last test case is followed by two zeros.
Output

For each test case output the answer on a single line.
Sample Input

5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
1
2
3
4
5
6
5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
Sample Output
8
1
8

問題分析與解題思路

本題我采用基于點的樹的分治進行求解


轉自漆子超論文算法合集之《分治算法在樹的路徑問題中的應用》

我們要尋找所有距離小于k的點對,則先在所有子數(shù)中尋找滿足要求的點對瑰排,個數(shù)記為X琢歇,再尋找路徑經過根佛吓,且距離小于k的點對蛇更,個數(shù)記為Y,最終結果為X+Y座慰。

(1)每次遞歸根的尋找--樹的重心

在點的分置過程中陨舱,第一步就是選取一個根翠拣,根據(jù)該根將整棵樹劃分為不同的子樹版仔。如果這個點是任意選取的,很有可能會使算法退化误墓,極端情況是整棵樹呈鏈狀蛮粮,若每次都選取鏈頂端節(jié)點作為根,則復雜度從logN退化為N谜慌。

樹重心的定義:樹的重心也叫樹的質心然想。找到一個點,其所有的子樹中最大的子樹節(jié)點數(shù)最少,那么這個點就是這棵樹的重心,刪去重心后,生成的多棵樹盡可能平衡欣范。

所以在分治的過程中变泄,每一次都將根選為當前樹的重心,可以提高算法速率恼琼。

(2)通過根的路徑距離計算

我們首先通過dfs計算每個節(jié)點t到根的距離dis[t],則i妨蛹,j兩個節(jié)點間距離為dis[i]+dis[j],并且i,j不屬于同一個子樹晴竞。

如果這樣考慮問題會變得比較麻煩蛙卤,我們可以考慮換一種角度:

  • 設X為滿足i<jdis[i]+dis[j]<=K的數(shù)對(i,j)的個數(shù)
  • 設Y為滿足i<jDepth[i]+Depth[j]<=KBelong[i]=Belong[j]數(shù)對(i,j)的個數(shù)

那么我們要統(tǒng)計的量便等于X-Y

(3)通過O(n)復雜度尋找滿足要求點對--排序的應用

求X噩死、Y的過程均可以轉化為以下問題:
已知dis[1],dis[2],...dis[m]颤难,求滿足i<jdis[i]+dis[j]<=K的數(shù)對(i,j)的個數(shù)

對于這個問題,我們先將dis從小到大排序已维。通過兩個指針l,r行嗤,l頭到尾掃描,r從尾向頭掃描垛耳,如果dis[l]+dis[r]<=K,l++,且符合條件點對個數(shù)增加(r-l)栅屏,因為如果當前l(fā)與r的組合滿足條件,ll+1,l+2...r-1的組合也必然滿足條件艾扮;否則r--既琴。

數(shù)據(jù)結構與算法設計及其主要代碼段

樹的分治

void work(int x)
{
    ans+=cal(x,0);
    vis[x]=1;
    for(int i=head[x];i;i=e[i].next)
    {
        if(vis[e[i].to])continue;
        ans-=cal(e[i].to,e[i].v);
        sum=son[e[i].to];
        root=0;
        getroot(e[i].to,root);
        work(root);
    }
}

尋找樹的重心

void getroot(int x,int fa)
{
    son[x]=1;f[x]=0;
    for(int i=head[x];i;i=e[i].next)
    {
        if(e[i].to==fa||vis[e[i].to])continue;
        getroot(e[i].to,x);
        son[x]+=son[e[i].to];
        f[x]=max(f[x],son[e[i].to]);
    }
    f[x]=max(f[x],sum-son[x]);
    if(f[x]<f[root])root=x;
}

計算以u為根的子樹中有多少點對的距離小于等于K

int cal(int x,int now)
{
    d[x]=now;deep[0]=0;
    getdeep(x,0);
    sort(deep+1,deep+deep[0]+1);
    int t=0,l,r;
    for(l=1,r=deep[0];l<r;)
    {
        if(deep[l]+deep[r]<=K){t+=r-l;l++;}
        else r--;
    }
    return t;
}

程序運行結果及分析

A. 算法復雜度
設遞歸最大層數(shù)為L,因為每一層的時間復雜度均為“瓶頸”——排序的時間復雜度O(NlogN)泡嘴,所以總的時間復雜度為O(L*NlogN)
參考http://blog.csdn.net/u010660276/article/details/44920725

B. 運行時間

內存 2944kB甫恩, 時間: 93ms(數(shù)據(jù)來自openjudge)

心得體會與總結

  1. 本題好難。酌予。磺箕。知識點很多奖慌,基于點的分治,重心求解松靡,O(n)掃描求解點對
  2. 細節(jié)很多简僧,遞歸終止條件,父節(jié)點的傳入等雕欺。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末岛马,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子屠列,更是在濱河造成了極大的恐慌啦逆,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笛洛,死亡現(xiàn)場離奇詭異夏志,居然都是意外死亡,警方通過查閱死者的電腦和手機苛让,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門沟蔑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狱杰,你說我怎么就攤上這事瘦材。” “怎么了浦旱?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵宇色,是天一觀的道長。 經常有香客問我颁湖,道長宣蠕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任甥捺,我火速辦了婚禮抢蚀,結果婚禮上,老公的妹妹穿的比我還像新娘镰禾。我一直安慰自己皿曲,他們只是感情好,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布吴侦。 她就那樣靜靜地躺著屋休,像睡著了一般。 火紅的嫁衣襯著肌膚如雪备韧。 梳的紋絲不亂的頭發(fā)上劫樟,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天,我揣著相機與錄音,去河邊找鬼叠艳。 笑死奶陈,一個胖子當著我的面吹牛,可吹牛的內容都是我干的附较。 我是一名探鬼主播吃粒,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拒课!你這毒婦竟也來了徐勃?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤捕发,失蹤者是張志新(化名)和其女友劉穎疏旨,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扎酷,經...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年遏匆,在試婚紗的時候發(fā)現(xiàn)自己被綠了法挨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡幅聘,死狀恐怖凡纳,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情帝蒿,我是刑警寧澤荐糜,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站葛超,受9級特大地震影響暴氏,放射性物質發(fā)生泄漏。R本人自食惡果不足惜绣张,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一答渔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧侥涵,春花似錦沼撕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嗦明,卻和暖如春笼沥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工敬拓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留邻薯,地道東北人。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓乘凸,卻偏偏與公主長得像厕诡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子营勤,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內容

  • 一年級語文上冊生字表 生字表一(共400字) 啊(ā)愛(ài)安(ān)岸(àn)爸(bà)八(bā)巴(bā)...
    meychang閱讀 2,804評論 0 6
  • sì 支zhī茶chá 對duì 酒jiǔ灵嫌,賦fù 對duì 詩shī,燕yàn子zi 對duì 鶯yīng 兒é...
    每個人的孟母堂閱讀 1,215評論 0 6
  • Zhōng huá zì jīng 中 華 字 經 dì yī bù fēn 第 一 部分 qián kūn yǒ...
    玉妖凰兒閱讀 2,717評論 0 9
  • 坐下來算算賬葛作,一天中究極花了多少時間在手機里寿羞。 算之前我估摸大概兩小時,實際一算赂蠢,頓時心疼起時間來了绪穆,何止兩個小時...
    心甲閱讀 198評論 1 0
  • 2017年7月14日 星期五 天氣晴 今天是妻子家侄子的生日,幾前天岳母就叮囑女兒虱岂,讓她這天來家...
    李佳怡爸爸閱讀 194評論 0 4