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