【原創】【演算法】【ygylca】狹義帶權並查集求lca兩點之間路徑最大路問題。

空灰冰魂發表於2014-08-21

題目:吉大附中oj,2527題。(http://oj.jdfz.com.cn/oldoj/problem.php?id=2527)

Description

NP去周遊世界,這一天他來到了西方極樂世界,這個地方有N座寺廟(標號由1到N),並且有N-1條道路聯通了這N座寺廟,NP也知道每條道路的長度,現在NP想知道從第i座寺廟到第j座寺廟的最短路上的邊權最大值是多少?你能幫他麼?

Input

第一行兩個正整數N,M。N表示N座寺廟,M表示有M個查詢。

(N<=40000   M<=40000)

接下來N-1行,每行三個正整數A、B、C。表示第A座寺廟到第B座寺廟有一條長為C的路。

接下來M行每行兩個正整數A、B。表示詢問A到B最短路徑上邊權的最大值。

Output

輸出M行每行輸出一個查詢結果。

Sample Input

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

Sample Output

4


題解:  ①用並查集維護一個陣列fc[i],表示i點到其當前祖先路線中的最長路徑,find函式壓縮路徑時順便維護。

        ②利用並查集求每個詢問的lca,在lca處加一個連結串列,每個詢問a->b都有a到lca中的最長路,b到lca的最長路,取大值作為詢問的解。


PS:NOIP2013-DAY1-貨車運輸

吉大附中oj-2228題。

http://oj.jdfz.com.cn/oldoj/problem.php?id=2228



//*********************************

程式碼:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 100000
#define max(a,b) a>b?a:b
 
typedef struct KSD
{
int u,v,next,l;//作為邊時l為len,詢問時l為lca
}ksd;ksd e[N],eq[N],el[N];
int head[N],headq[N],headl[N];
void add(int note,int u,int v,int l){e[note].u=u;e[note].v=v;e[note].l=l;e[note].next=head[u];head[u]=note;}
void addq(int note,int u,int v){eq[note].u=u;eq[note].v=v;eq[note].next=headq[u];headq[u]=note;}
void addl(int note,int u,int v){el[note].u=u;el[note].v=v;el[note].next=headl[u];headl[u]=note;}
int n,m,f[N],root[N],back[N],visit[N];//祖先和父親
int fc[N];
void init()
{
     int i;
     for(i=1;i<=n;i++)f[i]=i;
     memset(head,-1,sizeof(head));
     memset(headq,-1,sizeof(headq));
     memset(headl,-1,sizeof(headl));
     memset(visit,0,sizeof(visit));
     memset(fc,0,sizeof(fc));
}
int find(int x)
{
     int t=f[x];
     if(f[x]==x)return x;
     f[x]=find(f[x]);
     fc[x]=max(fc[x],fc[t]);
     return f[x];
}
void tjlca(int x,int p)
{
     int i,t,v,fv,tt;
     for(t=head[x];t!=-1;t=e[t].next)
     {
         v=e[t].v;
         if(v==p)continue;
         root[v]=x;
         back[v]=e[t].l;
         tjlca(v,x);
     }
     for(t=headq[x];t!=-1;t=eq[t].next)
     {
         v=eq[t].v;
         if(visit[v]==1)
         {
             fv=find(v);
             tt=(t+1)/2*2;
             eq[tt].l=fc[v];
             addl(tt,fv,x);
         }
     }
     for(t=headl[x];t!=-1;t=el[t].next)
     {
         v=el[t].v;
         find(v);
         eq[t].l=max(eq[t].l,fc[v]);
     }
     f[x]=p;
     fc[x]=back[x];
     visit[x]=1;
}

int main()
{
     //freopen("temple.in","r",stdin);
     int i,j,k;
     int a,b,c;
     int temp;
     scanf("%d%d",&n,&m);
     init();
     for(i=1;i<n;i++)
     {
         scanf("%d%d%d",&a,&b,&c);
         add(i*2-1,a,b,c);
         add(i*2,b,a,c);
     }
     for(i=1;i<=m;i++)
     {
         scanf("%d%d",&a,&b);
         addq(i*2-1,a,b);
         addq(i*2,b,a);
     }
     tjlca(1,1);
     for(i=1;i<=m;i++)printf("%d\n",eq[i*2].l);
     return 0;
}


相關文章