这题,真心整死人。。
首先,国家集训队论文里有一篇有关文章:
郭华阳 《RMQ与LCA问题》
然后有一个定理:
两点间最小瓶颈路一定是最小生成树上两点间唯一路径上的最大边
所以先求原图的最小生成树,这题就变成求树上两点间唯一路径上的最大边了
然后倍增? O(10000000∗log) O ( 10000000 ∗ l o g ) ?T到飞起。。再怎么卡常,LOJ跑得再快,依然为 O(不能过) O ( 不 能 过 )
#pragma GCC optimize(6)
#include<cstdio>
#include<algorithm>
#define rnd() (A=(A*B+C)%P)
#define __R register
#define IN inline
using namespace std;
const int maxn=(7e4)+5,maxE=(1e5)+5,Log=20,TT=1000000007;
template<typename Tp>IN Tp Max(Tp x,Tp y){
return x>y?x:y;}
int Ans,n,m,Q,A,B,C,P,fa[maxn],cnt[maxn];
struct ff{
int x,y,w;
IN bool operator <(const ff b)const{
return w<b.w;}
}E[maxE];
IN int getfa(int x){
return fa[x]==x?x:fa[x]=getfa(fa[x]);}
int tot,lnk[maxn],nxt[maxn<<1],son[maxn<<1],w[maxn<<1],dep[maxn],up[maxn][Log],val[maxn][Log],pow[Log],D[maxn];
IN void add_e(int x,int y,int z){son[++tot]=y,w[tot]=z,nxt[tot]=lnk[x],lnk[x]=tot;}
IN void DFS(int x,int dad){
dep[x]=dep[dad]+1;
for(__R int i=1;pow[i]<=dep[x];i++) up[x][i]=up[up[x][i-1]][i-1],val[x][i]=Max(val[x][i-1],val[up[x][i-1]][i-1]);
for(__R int j=lnk[x];j;j=nxt[j])if(son[j]!=dad){
up[son[j]][0]=x,val[son[j]][0]=w[j];
DFS(son[j],x);
}
}
IN int LCA(int x,int y){
int ans=0;
if(dep[x]<dep[y]){
int t=x;x=y,y=t;}
while(dep[x]>dep[y]){
if(ans<val[x][D[dep[x]-dep[y]]-1]) ans=val[x][D[dep[x]-dep[y]]-1];x=up[x][D[dep[x]-dep[y]]-1];}
if(x==y) return ans;
for(__R int k=D[dep[x]-1]-1;k>=0;k--) if(up[x][k]!=up[y][k]){
if(ans<val[x][k]) ans=val[x][k];if(ans<val[y][k]) ans=val[y][k];x=up[x][k],y=up[y][k];}
if(ans<val[x][0]) ans=val[x][0];if(ans<val[y][0]) ans=val[y][0];
return ans;
}
IN char gt(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,