比较好理解,相当于重建了一个二叉树,所有的父亲节点都为原来图中的边,儿子节点为点。
重构树就可以利用lca求两点间的最大(或者最小)边权以及一些树上操作。
较为简单的应用,需要用线段树来维护信息。
点击查看代码
#include<bits/stdc++.h>
using namespace std;const int N=1e6;
int n,m,q;
int f[N][40],fa[N],tme[N];
int ls[N],rs[N],dis[N];int find(int x)
{return fa[x]==x?x:fa[x]=find(fa[x]);
}int dep[N];
void dfs(int u,int fat)
{dep[u]=dep[fat]+1;f[u][0]=fat;for(int i=1;i<=30;i++) f[u][i]=f[f[u][i-1]][i-1];if(ls[u]!=0) dfs(ls[u],u);if(rs[u]!=0) dfs(rs[u],u);
}int lca(int x,int y)
{if(dep[x]<dep[y]) swap(x,y);for(int i=30;i>=0;i--){if(dep[y]<=dep[f[x][i]]){x=f[x][i];}}if(x==y) return x;for(int i=30;i>=0;i--){if(f[x][i]!=f[y][i]){x=f[x][i];y=f[y][i];}}return f[x][0];
}#define lson (rt<<1)
#define rson (rt<<1|1)void pushup(int rt)
{dis[rt]=lca(dis[lson],dis[rson]);
}void build(int rt,int l,int r)
{if(l==r) {dis[rt]=l;return ;}int mid=(l+r)>>1;build(lson,l,mid); build(rson,mid+1,r);pushup(rt);
}int query(int rt,int l,int r,int L,int R)
{if(L<=l&&r<=R) return dis[rt];int mid=(l+r)>>1;int ans=0;if(L<=mid) ans=query(lson,l,mid,L,R);if(R>mid) ans= ans==0?query(rson,mid+1,r,L,R):lca(ans,query(rson,mid+1,r,L,R));return ans;
} int main()
{scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=n*2-1;i++) fa[i]=i;for(int i=1;i<=n*2-1;i++) ls[i]=rs[i]=tme[i]=0;int cnt=n;for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);int fx=find(x),fy=find(y);if(fx!=fy){int u=++cnt;tme[u]=i;ls[u]=fx;rs[u]=fy;fa[fx]=fa[fy]=u;} }dfs(cnt,0);build(1,1,n);for(int i=1;i<=q;i++){int l,r;scanf("%d%d",&l,&r);printf("%d\n",tme[query(1,1,n,l,r)]);} }