题解:CF2057E2 Another Exercise on Graphs (hard version)
E1
先将所有边按照边权排序,考虑在询问时二分答案。
设现在二分到了第
那么考虑预处理出
E2
因为这个图的边权只有
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,m,q,a,b,k,f[405][405][405],fa[405],g[405][405];
struct ee{
int u,v,w;
friend bool operator<(const ee&a,const ee&b){
return a.w<b.w;
}
}e[160005],ed[405];
int find(int x){
return(fa[x]==x)?x:fa[x]=find(fa[x]);
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>t;
while(t--){
cin>>n>>m>>q;
for(int i=1;i<=n;i++)fa[i]=i;
memset(g,0x3f,sizeof g);
for(int i=1;i<=m;i++)cin>>e[i].u>>e[i].v>>e[i].w,g[e[i].u][e[i].v]=g[e[i].v][e[i].u]=1;
for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
sort(e+1,e+m+1);
int cnt=0;
for(int i=1;i<=n;i++)g[i][i]=0;
for(int i=0;i<=n-1;i++)for(int j=1;j<=n;j++)for(int k=1;k<=n;k++)f[i][j][k]=g[j][k];
for(int i=1;i<=m;i++){
int fx=find(e[i].u),fy=find(e[i].v);
if(fx==fy)continue;cnt++;
ed[cnt]=e[i],fa[fx]=fy;
for(int x=1;x<=n;x++)for(int y=1;y<=n;y++){
f[cnt][x][y]=min({f[cnt-1][x][y],f[cnt-1][x][e[i].u]+f[cnt-1][y][e[i].v],f[cnt-1][x][e[i].v]+f[cnt-1][y][e[i].u]});
}
}
while(q--){
cin>>a>>b>>k;
int l=1,r=cnt,ans=0;
while(l<=r){
int mid=l+r>>1;
if(f[mid][a][b]<k)ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ed[ans].w<<" ";
}
cout<<"\n";
}
}