传送门
这个题我本来看出来了,也想到做法了,然后打了130行的代码,开始调,好不容易调过样例,然后就交;
第一次CE,改了继续交;
第二次10分,我当时就崩溃,我写了这么长时间,还不如30分无脑暴力??我就看题解,果然算法就是这样,然后,比对了好几个,也没看见什么错,倒是跟着他们优化了优化常数,然后又交;
第三次还是10分,我已经麻木了,放弃了看题解,开始对着自己的代码肉眼debug,结果又优化了好多小常数,还是看不出来错误;
第四次当然没变化,我就开始对着代码发呆,看呀看,看呀看,不知道过了多久,我看了不知道多少遍代码之后,我发现了一丝不对劲,我的lca预处理怎么怪怪的,我就翻出来以前的lca,对比,发现我的代码是倒着算的!立刻改了,然后调了一会儿,就过样例了,然后交;
第五次AC!!
全程用时:1.5h+
真的今天运气太烂,洛谷的大凶还是很准的。。。
题解
首先看题,大概是这样:
给定一个无向图,多次询问两点之间路径上最大边最小化。
首先,它只问最大,所以可以直接转化成Kruskal最大生成树,然后一边倍增lca一边预处理一下,就可以像lca那样log查询了。
这题就是不好调试。。。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
struct edge{
int x,y,w;
inline bool operator < (const edge& b) const {
return w>b.w;
}
}e[100001];
int head[100001];
int to[100001];
int nxt[100001];
int w[100001];
int n,m;
int tot;
int fa[10001];
int st[10001][17];
int mn[10001][17];
int use[100001];
int dep[100001];
int vis[100001];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
inline void addedge(int x,int y,int l){
tot++;
e[tot].x=x;
e[tot].y=y;
e[tot].w=l;
}
inline void addedge2(int x,int y,int l){
tot++;
to[tot]=y;
nxt[tot]=head[x];
head[x]=tot;
w[tot]=l;
}
void dfs(int x,int father,int l){
vis[x]=1;
dep[x]=dep[father]+1;
mn[x][0]=l;
st[x][0]=father;
for(int i=head[x];i;i=nxt[i]){
if(vis[to[i]]){
continue;
}
dfs(to[i],x,w[i]);
}
}
void getst(){
for(int i=1;i<=n;i++){
if(!vis[i]){
dfs(i,0,0);
}
}
for(int k=1;k<=16;k++){
for(int i=1;i<=n;i++){
st[i][k]=st[st[i][k-1]][k-1];
mn[i][k]=min(mn[i][k-1],mn[st[i][k-1]][k-1]);
}
}
}
int getlca(int x,int y){
int ans=0x3f3f3f3f;
if(dep[x]>dep[y]){
swap(x,y);
}
for(int k=16;k>=0;k--){
if(st[y][k])
if(dep[st[y][k]]>=dep[x]){
ans=min(ans,mn[y][k]);
y=st[y][k];
if(dep[x]==dep[y])break;
}
}
if(x==y){
return ans;
}
for(int k=16;k>=0;k--){
if(st[x][k]!=st[y][k]){
ans=min(ans,mn[x][k]);
ans=min(ans,mn[y][k]);
x=st[x][k];
y=st[y][k];
}
}
return min(ans,min(mn[x][0],mn[y][0]));
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int x,y,l;
scanf("%d %d %d",&x,&y,&l);
addedge(x,y,l);
}
sort(e+1,e+m+1);
tot=0;
for(int i=1,j=n;i<=m&&j!=1;i++){
int u=find(e[i].x);
int v=find(e[i].y);
if(u!=v){
fa[u]=v;
j--;
use[i]=1;
addedge2(e[i].x,e[i].y,e[i].w);
addedge2(e[i].y,e[i].x,e[i].w);
}
}
getst();
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++){
int x,y;
scanf("%d %d",&x,&y);
if(find(x)!=find(y)){
printf("-1
");
continue;
}
int num=getlca(x,y);
printf("%d
",num);
}
return 0;
}