【原创】【算法】【ygylca】狭义带权并查集求lca两点之间路径最大路问题。

题目:吉大附中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;
}


你可能感兴趣的:(ygylca)