倍增lca--luogu3013貨車運輸
阿新 • • 發佈:2019-02-01
突發奇想寫部落格233
倍增lca。
先預處理出一個二維陣列,f[x][i]表示x節點的2^i的祖先是誰
在樹上dfs出各個點的深度順便求了f
在找lca的時候
先把兩個點調整到一個深度
如果調整完已經到同一個點上就退出
如果沒有就開始往上跳
從最大的開始跳
直到跳到相同的點
然後順便更新res的值
還有這道題要先求最長路建一顆樹··
粘程式碼
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 10000
#define mx 100000
using namespace std;
int n,m,q,cnt,head[maxn],depth[maxn],f[maxn][32],fa[maxn];
int num,hd[maxn],root,w[maxn][32];
bool check[maxn];
struct node{
int to,nxt,w,frm;
}edge[mx];
struct nd{
int to,nxt,w;
}e[mx];
struct nnnn{
int p[maxn];
}nod[maxn];
bool cmp(node x,node y)
{
return x.w>y.w;
}
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void add(int x,int y,int z)
{
cnt++;
edge[cnt].to=y;
edge[cnt].frm=x;
edge[cnt].nxt=head[x];
edge[cnt].w=z;
head[x]=cnt;
}
void buil(int x,int y,int z)
{
num++;
e[num].to=y;
e[num].nxt=hd[x];
e[num].w=z;
hd[x]=num;
}
void kruscal()
{
sort(edge+1,edge+cnt+1,cmp);
int k=0;
for(int i=1;i<=cnt;i++)
{
int u=edge[i].frm,v=edge[i].to;
if(find(u)!=find(v))
{
fa[find(v)]=find(u);
buil(u,v,edge[i].w); buil(v,u,edge[i].w);
k++;
}
if(k==n-1) break;
}
return ;
}
void dfs(int u,int father,int d)
{
check[u]=1;
f[u][0]=father;
depth[u]=d;
for (register int i=hd[u];i;i=e[i].nxt)
{
int v=e[i].to;
if (check[v]==0)
{
w[v][0]=e[i].w;
dfs(v,u,d+1);
}
}
}
int bzlca(int x,int y)
{
int res=0x3f3f3f3f;
if(depth[x]<depth[y]) swap(x,y);
for(int i=20;i>=0;i--)
{
if(depth[f[x][i]]>=depth[y])
{
res=min(res,w[x][i]);
x=f[x][i];
}
}
if(x==y)
{
return res;
}
for(int i=20;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
res=min(res,min(w[x][i],w[y][i]));
x=f[x][i];
y=f[y][i];
}
}
res=min(res,min(w[x][0],w[y][0]));
return res;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
kruscal();
for(int i=1;i<=n;i++)
{
if(check[i]==0)
{
depth[i]=1;
dfs(i,0,1);
}
}
for(int j=1;j<=20;j++)
for(int i=1;i<=n;i++)
{
f[i][j]=f[f[i][j-1]][j-1];
w[i][j]=min(w[i][j-1],w[f[i][j-1]][j-1]);
}
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(find(a)!=find(b)) printf("-1\n");
else printf("%d\n",bzlca(a,b));
}
return 0;
}