/* 终于没有看题解写出了一道noip T3难度的题(虽然wmy简单点拨了一下 ^^) 联通所有点 路上维护最小权值 使最小权值 很像最小生成树嘛 但是他要的是最小的最大 二分不单调似乎 所以先最大生成树建图 这样就得到了n-1条边链接n个节点 又是维护两两节点之间的路上最小值 很容易想到LCA 怎么维护呢 开始想想 嗯 树的规模应该不会很大 嗯 不用倍增思想应该以跑的挺快 所以第一遍只维护了dis 表示到上面的点距离 然后嘛 很猥琐的 a=f[a][0] 一层一层的找 既然是树了 应该也挺快的嘛 在COGS上交A了 哈哈哈数据弱 然而在codevs上T了3个点 好吧 下面是85分代码 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 50010 using namespace std; int n,m,q,num,head[maxn],tot,fa[maxn],f[maxn][20],dep[maxn],dis[maxn]; struct node { int u,v,t,pre; }e[maxn*2]; struct Node { int u,v,t; }p[maxn*2]; int init() { int x=0;char s=getchar(); while(s<'0'||s>'9')s=getchar(); while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x; } int cmp(const Node &x,const Node &y) { return x.t>y.t; } int find(int x) { if(x!=fa[x])fa[x]=find(fa[x]); return fa[x]; } void Add(int from,int to,int dis) { num++; e[num].u=from;e[num].v=to;e[num].t=dis; e[num].pre=head[from];head[from]=num; } void Dfs(int now,int from,int c,int Dis) { f[now][0]=from;dep[now]=c;dis[now]=Dis; for(int i=head[now];i;i=e[i].pre) if(e[i].v!=from) Dfs(e[i].v,now,c+1,e[i].t); } void Get_fa() { for(int j=1;j<=17;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1]; } int LCA(int a,int b) { int ret=0x3f3f3f3f; if(dep[a]<dep[b])swap(a,b); int t=dep[a]-dep[b]; for(int i=1;i<=t;i++) { ret=min(ret,dis[a]); a=f[a][0]; } while(a!=b) { ret=min(ret,dis[a]); ret=min(ret,dis[b]); a=f[a][0];b=f[b][0]; } return ret; } int main() { n=init();m=init(); int x,y,z; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) { x=init();y=init();z=init(); p[i].u=x;p[i].v=y;p[i].t=z; } sort(p+1,p+1+m,cmp); for(int i=1;i<=m;i++) { int u=p[i].u,v=p[i].v; int r1=find(u);int r2=find(v); if(r1!=r2) { Add(u,v,p[i].t);Add(v,u,p[i].t); fa[r2]=r1; tot++;if(tot==n-1)break; } } q=init();memset(dis,127/3,sizeof(dis)); Dfs(1,1,0,0);Get_fa(); for(int i=1;i<=q;i++) { x=init();y=init(); int ans=LCA(x,y); if(ans>=707406378)ans=-1; printf("%d ",ans); } } /* 下午听wmy一说 发现可以有办法跑的飞快 既然我们能维护i往上2^j 层是谁 我们也可以顺便维护i往上2^j 层路上的最小值 然后 非常愉快的再找lca时顺便更新下答案就ok啦 至于-1的情况嘛 如果建完图后不在图里的自然就到不了了 怎么算是不在图里呢 深度为0且不是1 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 50010 using namespace std; int n,m,q,num,head[maxn],tot,fa[maxn],f[maxn][20],dep[maxn],dis[maxn][20]; struct node { int u,v,t,pre; }e[maxn*2]; struct Node { int u,v,t; }p[maxn*2]; int init() { int x=0;char s=getchar(); while(s<'0'||s>'9')s=getchar(); while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x; } int cmp(const Node &x,const Node &y) { return x.t>y.t; } int find(int x) { if(x!=fa[x])fa[x]=find(fa[x]); return fa[x]; } void Add(int from,int to,int dis) { num++; e[num].u=from;e[num].v=to;e[num].t=dis; e[num].pre=head[from];head[from]=num; } void Dfs(int now,int from,int c,int Dis) { f[now][0]=from;dep[now]=c;dis[now][0]=Dis; for(int i=head[now];i;i=e[i].pre) if(e[i].v!=from) Dfs(e[i].v,now,c+1,e[i].t); } void Get_fa() { for(int j=1;j<=17;j++) for(int i=1;i<=n;i++) { f[i][j]=f[f[i][j-1]][j-1]; dis[i][j]=min(dis[i][j-1],dis[f[i][j-1]][j-1]); } } int LCA(int a,int b) { if(a!=1&&dep[a]==0)return -1; if(b!=1&&dep[b]==0)return -1; int ret=0x3f3f3f3f; if(dep[a]<dep[b])swap(a,b); int t=dep[a]-dep[b]; if(t) for(int i=0;i<=17;i++) if(t&(1<<i)) { ret=min(ret,dis[a][i]); a=f[a][i]; } if(a==b)return ret; for(int i=17;i>=0;i--) if(f[a][i]!=f[b][i]) { ret=min(ret,dis[a][i]); ret=min(ret,dis[b][i]); a=f[a][i];b=f[b][i]; } ret=min(ret,min(dis[a][0],dis[b][0])); return ret; } int main() { n=init();m=init(); int x,y,z; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) { x=init();y=init();z=init(); p[i].u=x;p[i].v=y;p[i].t=z; } sort(p+1,p+1+m,cmp); for(int i=1;i<=m;i++) { int u=p[i].u,v=p[i].v; int r1=find(u);int r2=find(v); if(r1!=r2) { Add(u,v,p[i].t);Add(v,u,p[i].t); fa[r2]=r1; tot++;if(tot==n-1)break; } } q=init();memset(dis,127/3,sizeof(dis)); Dfs(1,1,0,0);dis[1][0]=0x3f3f3f3f;Get_fa(); for(int i=1;i<=q;i++) { x=init();y=init(); int ans=LCA(x,y); printf("%d ",ans); } return 0; }