1.跑出最大生成森林。
2.选取一个超级根,把所有树连接起来。
3.树链剖分,线段树维护最小值。
注意:如果把边上的权值转移到点上,要注意在求值的时候LCA点要不要算上去。
#include
#include
using namespace std;
#define N 100050
#define to e[i].v
#define inf 1000000000
int size[N],head[N],fa[N],val[N],deep[N],pos[N],bl[N],used[N],low[N<<2],vis[N],father[N];
int cnt,id,n,m,sz,k;
struct Node{int u,v,w;}f[N];
struct node{int next,v,w;}e[N];
bool cmp(Node A,Node B){return A.w>B.w;}
void add(int u,int v,int w) {e[id].v=v; e[id].next=head[u]; e[id].w=w; head[u]=id++;}
int min(int a,int b) {return a>b? b:a;}
int swap(int &a,int &b) {int t=a;a=b;b=t;}
int find(int x) {return x==father[x]? x:father[x]=find(father[x]);}
void dfs1(int u)
{
size[u]=1;
for (int i=head[u];i;i=e[i].next)
if (to^fa[u])
{
val[to]=e[i].w;
fa[to]=u;
deep[to]=deep[u]+1;
dfs1(to);
size[u]+=size[to];
}
}
void dfs2(int u,int chain)
{
pos[u]=++sz; bl[u]=chain;
int k=0;
for (int i=head[u];i;i=e[i].next)
if (deep[to]>deep[u] && size[to]>size[k]) k=to;
if (!k) return; dfs2(k,chain);
for (int i=head[u];i;i=e[i].next)
if (deep[to]>deep[u] && k^to) dfs2(to,to);
}
void pushup(int root) {low[root]=min(low[root<<1],low[root<<1|1]);}
void insert(int root,int l,int r,int x,int y)
{
if (l==r)
{
low[root]=y;
return;
}
int mid=l+r>>1;
if (x<=mid) insert(root<<1,l,mid,x,y);
if (mid>1,ans=inf;
if (L<=mid) ans=min(ans,query(root<<1,l,mid,L,R));
if (midpos[y]) swap(x,y);
ans=min(ans,query(1,1,n,pos[x]+1,pos[y]));
return ans;
}
int main()
{
scanf("%d%d",&n,&m); id=1;
for (int i=1;i<=m;i++)
{
int u,v,w; scanf("%d%d%d",&u,&v,&w);
f[i].u=u; f[i].v=v; f[i].w=w;
}
sort(f+1,f+m+1,cmp);
for (int i=1;i<=n;i++) father[i]=i;
for (int i=1;i<=m;i++)
{
int u=f[i].u,v=f[i].v,w=f[i].w,fu=find(u),fv=find(v);
if (fu^fv)
{
father[fu]=fv;
add(u,v,w); add(v,u,w);
}
}
for (int i=1;i<=n;i++) int u=find(i);
int root=++n;
for (int i=1;i<=n;i++) vis[father[i]]=1;
for (int i=1;i<=n;i++)
if (vis[i]) add(root,i,inf),add(i,root,inf);
dfs1(root); dfs2(root,root);
scanf("%d",&k);val[root]=inf;
for (int i=1;i<=n;i++) insert(1,1,n,pos[i],val[i]);
for (int i=1;i<=k;i++)
{
int u,v;
scanf("%d%d",&u,&v);
if (father[u]^father[v]) puts("-1");else printf("%d\n",getmin(u,v));
}
return 0;
}