【原創】【演算法】【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;
}
相關文章
- 並查集到帶權並查集並查集
- 求兩點之間最短路徑-Dijkstra演算法演算法
- 樹(tree) - 題解(帶權並查集)並查集
- 面試常考演算法題之並查集問題面試演算法並查集
- (UVA - 208)Firetruck(路徑輸出問題,回溯+並查集/floyd演算法+dfs)並查集演算法
- 並查集系列之「路徑壓縮( path compression ) 」並查集路徑壓縮
- 【資料結構】帶權並查集資料結構並查集
- 【帶權並查集】理論和應用並查集
- POJ 2492-A Bug's Life(帶權並查集)並查集
- 關於並查集問題並查集
- 【並查集】【帶偏移的並查集】食物鏈並查集
- 演算法——路徑問題演算法
- HDU 3038 How Many Answers Are Wrong (帶權並查集)並查集
- [最短路徑問題]Dijkstra演算法(含還原具體路徑)演算法
- bzoj4690: Never Wait for Weights(帶權並查集)AI並查集
- 關押罪犯 擴充套件域並查集 帶權並查集 二分圖+二分套件並查集
- 並查集演算法並查集演算法
- HDU-3635 Dragon Balls 並查集路徑壓縮Go並查集路徑壓縮
- 求 LCA
- [kuangbin帶你飛]專題五 並查集 題解並查集
- 並查集(二)並查集的演算法應用案例上並查集演算法
- CHOJ 4101 銀河英雄傳說【邊帶權並查集】並查集
- POJ 2492 A bug's life【擴充套件域 | 邊帶權並查集】套件並查集
- RAC節點之間通訊問題 兩節點 11g RAC
- 演算法與資料結構之並查集演算法資料結構並查集
- RMQ求lcaMQ
- 並查集題目合集並查集
- poj 1182 並查集經典問題並查集
- week2 kuangbin 題單 最短路問題 + 並查集問題並查集
- Python實現求多個集合之間並集的方法Python
- POJ 1182 食物鏈【擴充套件域 | 邊帶權並查集】套件並查集
- DFN 序求 LCA
- 【並查集】一種與時間賽跑的巧妙演算法並查集演算法
- Linux求兩個文字檔案的交集、差集、並集Linux
- 並查集在實際問題中的應用並查集
- 簡單易懂的並查集演算法以及並查集實戰演練並查集演算法
- [譯] Swift 演算法學院 - 並查集Swift演算法並查集
- 【演算法】並查集的運用演算法並查集