传送药水
(喝了这一壶传送药水,保你看了什么题都觉得神清气爽)
这题不算水。
首先想到,肯定需要跑一遍最大生成树,因为我们需要尽可能大的限制。
那么,接下来就是求两点之间最小限制。
那么就是我们就可以用求LCA(最近公共祖先)来解决这个问题。
所以就倍增好了。
我们这里倍增的有两个数组,一个是祖先,另一个是当前点到祖先的路上的最小限制。
最后理一遍思路:
先kruskal建立一个最大树(图)。
然后bfs建立一个树,处理一些基本数据。
然后就用倍增求LCA来解决就好了。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
struct edge{
int u,v,w;
};
int n,m;
int p[10005];
edge e[50005];
int f[10005][21],deep[10005];
int g[10005][21];
int vis[10005];
vector<int> G[10005],H[10005];
//int fa[10005];
int ques;
int find(int xx){
return xx==p[xx]?xx:p[xx]=find(p[xx]);
}
int cmp(edge a,edge b){
return a.w>b.w;
}
void kruscal(){
sort(e,e+m,cmp);
for(int i=1;i<=n;i++){
p[i]=i;
}
for(int i=0;i<m;i++){
int xx=find(e[i].u),yy=find(e[i].v);
if(xx!=yy){
p[xx]=yy;
G[e[i].u].push_back(e[i].v);
G[e[i].v].push_back(e[i].u);
H[e[i].u].push_back(e[i].w);
H[e[i].v].push_back(e[i].w);
}
}
}
void bfs(){
memset(g,0x3f,sizeof(g));
memset(vis,0,sizeof(vis));
memset(f,-1,sizeof(f));
queue<int> q;
int cur=3;
deep[cur]=1;
q.push(cur);
vis[cur]=1;
// f[cur][0]=-1;
// fa[cur]=-1;
while(!q.empty()){
cur=q.front();
q.pop();
int len=G[cur].size();
for(int i=0;i<len;i++){
if(vis[G[cur][i]]==0){
q.push(G[cur][i]);
vis[G[cur][i]]=1;
deep[G[cur][i]]=deep[cur]+1;
f[G[cur][i]][0]=cur;
// fa[G[cur][i]]=cur;//待定
g[G[cur][i]][0]=H[cur][i];
}
}
}
}
void init(){
for(int k=0;k<20;k++){
for(int j=1;j<=n;j++){
if(f[j][k]!=-1){
f[j][k+1]=f[f[j][k]][k];
g[j][k+1]=min(g[j][k],g[f[j][k]][k]);
}
}
}
}
int ans;
int jump(int u,int step){
for(int k=0;k<21;k++){
if(step&(1<<k)){
ans=min(ans,g[u][k]);
u=f[u][k];
}
}
return u;
}
void lca(int u,int v){
ans=0x3f3f3f3f;
if(deep[u]<deep[v]){
swap(u,v);
}
u=jump(u,deep[u]-deep[v]);
for(int k=20;k>=0;k--){
if(f[u][k]!=f[v][k]){
ans=min(min(ans,g[u][k]),g[v][k]);
u=f[u][k];
v=f[v][k];
}
}
ans=u==v?ans:min(min(ans,g[u][0]),g[v][0]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
e[i].w=0;
}
for(int i=0;i<m;i++){
int ww;
scanf("%d%d%d",&e[i].u,&e[i].v,&ww);
e[i].w=max(e[i].w,ww);
}
kruscal();
bfs();
init();
scanf("%d",&ques);
while(ques--){
int u,v;
scanf("%d%d",&u,&v);
if(u>n||v>n){
printf("-1\n");
continue;
}
if(find(u)!=find(v)){
printf("-1\n");
continue;
}else{
lca(u,v);
if(ans<0x3f3f3f3f){
printf("%d\n",ans);
}else{
printf("-1\n");
}
}
}
return 0;
}