竟然一次A掉了...
首先用kruskal构建一颗最大生成树。(因为要使最小边最大,则这条边一定在最大生成树上)
于是每次询问就转变为在一棵树上询问两点到LCA的最小边权,用倍增法解决。
顺便复习了一下并查集写法。。。T_T
#include
#include
#include
#include
#include
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair
#define MAXN 10005
#define MAXM 50005
#define INF 1000000000
using namespace std;
int n,m,q,x,y,cnt=0;
int p[MAXN],d[MAXN],ver[MAXM*2],head[MAXN],f[MAXN][20],g[MAXN][20];
bool vst[MAXN];
struct edge_type
{
int next,to,w;
}e[MAXN*2];
struct data
{
int x,y,z;
}a[MAXM];
int read()
{
int ret=0,flag=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') flag=-1;ch=getchar();}
while (ch>='0'&&ch<='9') {ret=ret*10+ch-'0';ch=getchar();}
return ret*flag;
}
void add_edge(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].next=head[u];
e[cnt].w=w;
head[u]=cnt;
}
void dfs(int x,int dep)
{
vst[x]=true;
d[x]=dep;
for(int i=head[x];i;i=e[i].next) if (!vst[e[i].to])
{
f[e[i].to][0]=x;
g[e[i].to][0]=e[i].w;
dfs(e[i].to,dep+1);
}
}
bool cmp(data d1,data d2)
{
return d1.z>d2.z;
}
int find(int x)
{
if (p[x]!=x) p[x]=find(p[x]);
return p[x];
}
void kruskal()
{
sort(a+1,a+m+1,cmp);
F(i,1,n) p[i]=i;
F(i,1,m)
{
int fx=find(a[i].x),fy=find(a[i].y);
if (fx==fy) continue;
p[fx]=fy;
add_edge(a[i].x,a[i].y,a[i].z);
add_edge(a[i].y,a[i].x,a[i].z);
}
}
int lca_min(int a,int b)
{
if (a==b) return 0;
int ret=INF;
if (d[a]=d[b])
{
ret=min(ret,g[a][i]);
a=f[a][i];
}
if (a==b) return ret;
D(i,k,0) if (f[a][i]&&f[a][i]!=f[b][i])
{
ret=min(ret,min(g[a][i],g[b][i]));
a=f[a][i];
b=f[b][i];
}
ret=min(ret,min(g[a][0],g[b][0]));
return ret;
}
int main()
{
memset(head,0,sizeof(head));
memset(vst,false,sizeof(vst));
memset(f,0,sizeof(f));
memset(g,127,sizeof(g));
n=read();m=read();
F(i,1,m) {a[i].x=read();a[i].y=read();a[i].z=read();}
q=read();
kruskal();
dfs(1,1);
for(int j=1;(1<