HDU 2586 How far away? Tarjan演算法 並查集 LCA

來源:互聯網
上載者:User

標籤:har   思路   oid   回溯   lag   就是   code   fir   修改   

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 23506    Accepted Submission(s): 9329

Problem DescriptionThere are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can‘t visit a place twice) between every two houses. Yout task is to answer all these curious people. 

 

InputFirst line is a single integer T(T<=10), indicating the number of test cases.
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j. 


OutputFor each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case. 


Sample Input23 21 2 103 1 151 22 3  2 21 2 1001 22 1 Sample Output1025 100100  本題大意:  給出一棵樹,和樹邊長度,給出一系列詢問點,求兩點間的距離。
 解題思路:  本題可用Tarjan演算法求出根節點到各點的最短距離,然後結合并查集來先求出最近公用祖先(LCA),這樣兩個點之間的距離就可以表示為:根節點到點1的距離 + 根節點到點2的距離 - 兩倍的根節點到LCA的距離。  思想核心是求LCA,所以本文記錄一個用Tarjan結合并查集求LCA的方法。  實現方法:選定一個點為根節點,對樹進行DFS搜尋,搜尋回溯時把子節點的並查集資訊連到父節點上去。在搜尋每個點的時候,都檢查是否是詢問點,如果是詢問點,則檢查與之對應的詢問點是否被訪問過,如果訪問過,那麼它的並查集父親必然到知道他們的公用祖先上去,為什麼?這是我參考其他大神代碼的時候思考一段時間才想出來為什麼的。根據DFS搜尋的特性,搜尋回溯時都把下級的並查集資訊往上連,而DFS是深度優先,則回溯距離必然盡可能小,即如果回溯一級就找到另一條路的話,就會繼續往下搜,而如果這兩條路上各存著詢問點對的其中一個,先被搜尋到的那個節點的並查集資訊只往上並了一級,那就是最近的公用祖先。在處理尋問點對的時候,如果找到這樣的並查集被修改過的(即被訪問過的)的對應點,那就把它們兩個的LCA記下即可。  把整棵樹遍歷完的時候,所有詢問點對的LCA也都求出來了,最後按照尋問順序,按照公式計算並輸出距離即可。 結合一下AC代碼理解:
#include<bits/stdc++.h>using namespace std;#define N 40000typedef struct Edge{    int t,v;    int next;}edge;edge E[N*2],e[N*2];int cnt;int head1[N],head2[N];//head1用於樹上節點的串連,head2用於詢問節點的串連int dis[N],f[N],vis[N];//dis各點到根節點的距離,f為並查集int ans[N][3];          //ans[0]和[1]記錄詢問點對,ans[3]記錄他們的公用祖先(LCA)int n,m;void addedge(int u,int v,int d,edge *a,int *head){    a[cnt].t=v;    a[cnt].v=d;    a[cnt].next=head[u];    head[u]=cnt++;    a[cnt].t=u;    a[cnt].v=d;    a[cnt].next=head[v];    head[v]=cnt++;}int findx(int a)//並查集{    if(a!=f[a])        return f[a]=findx(f[a]);    return a;}void getLCA(int p)//Tarjan演算法求LCA{    vis[p]=1;    f[p]=p;        //進入時初始化並查集    for(int i=head2[p];i!=-1;i=e[i].next)//檢查詢問點對,是否發現已訪問    {        if(vis[e[i].t])            ans[e[i].v][2]=findx(e[i].t);    }    for(int i=head1[p];i!=-1;i=E[i].next)//DFS搜尋    {        if(!vis[E[i].t])        {            dis[E[i].t]=dis[p]+E[i].v;  //更新距離            getLCA(E[i].t);            f[E[i].t]=p;                //搜尋過後更新子節點的並查集        }    }}int main(){    //freopen("a.txt","r",stdin);    int T;    scanf("%d",&T);    while(T--)    {        cnt=0;        memset(head1,-1,sizeof(head1));        memset(head2,-1,sizeof(head2));        scanf("%d%d",&n,&m);        for(int i=1;i<=n-1;i++)        {            int a,b,v;            scanf("%d%d%d",&a,&b,&v);            addedge(a,b,v,E,head1);        }        cnt=0;        for(int i=1;i<=m;i++)       //先全部記錄後離線處理        {            scanf("%d%d",&ans[i][0],&ans[i][1]);            addedge(ans[i][0],ans[i][1],i,e,head2);        }        memset(vis,0,sizeof(vis));        dis[1]=0;        getLCA(1);        for(int i=1;i<=m;i++)            printf("%d\n",dis[ans[i][1]]+dis[ans[i][0]]-2*dis[ans[i][2]]);    }       //最短距離 = 節點1的距離 + 節點2的距離 - 2*LCA的最短距離}           //(這裡最短距離是指導根節點的距離)

 

HDU 2586 How far away? Tarjan演算法 並查集 LCA

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.