题意
给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。
图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).
现在有 K个询问 (1 < = K < = 20,000)。
每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
解析
类似于那啥货车运输,嗯,懒得倍增就打了树链剖分。
#include <cstdio>
#include <algorithm>
#define Rep( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i<=(i##_END);i++)
#define For( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i++)
#define Lop( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i>=(i##_END);i--)
#define Dnt( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i--)
using std :: max;
using std :: min;
const int maxx = 15000 + 25;
const int maxm = 30000 + 25;
const int Inf = (unsigned)(-1) >> 1;
typedef int Array[maxx];
int n,m,x,y,z,num,cnt,ans,tot,t;
int head[maxx],to[maxm],nxt[maxm],w[maxm];
int Tx[maxx<<2];
Array v,top,dpt,ftr,son,size,fky,rnk;
class Edges{
public:
int x;
int y;
int v;
}a[maxm<<1];
bool cmp(Edges a,Edges b) {return a.v < b.v;}
namespace Segment_Tree{
void modify(int i,int pos,int l,int r,int k){
if(l == r) {Tx[i] = k;return;}
int mid = (l+r) >> 1;
if(pos <= mid) modify(i<<1,pos,l,mid,k);
if(pos > mid) modify(i<<1|1,pos,mid+1,r,k);
Tx[i] = max(Tx[i<<1],Tx[i<<1|1]);
}
int Query(int i,int x,int y,int l,int r){
if(x <= l && r <= y) return Tx[i];
int ans = -Inf;
int mid = (l+r) >> 1;
if(x <= mid) ans = max(ans,Query(i<<1,x,y,l,mid));
if(y > mid) ans = max(ans,Query(i<<1|1,x,y,mid+1,r));
return ans;
}
}
namespace Kruskal{
int find(int x){
return x == fky[x]? x : fky[x] = find(fky[x]);
}
}
namespace Cute{
using namespace Segment_Tree;
void Ins(int x,int y,int z){
to[++num] = y;w[num] = z;nxt[num] = head[x];head[x] = num;
}
void Dfs(int x){
size[x] = 1;
for(int i=head[x];i;i=nxt[i]){
if(to[i] == ftr[x]) continue;
dpt[to[i]] = dpt[x] + 1;
ftr[to[i]] = x;
v[to[i]] = w[i];
Dfs(to[i]);size[x] += size[to[i]];
if(size[to[i]] > size[son[x]]) son[x] = to[i];
}
}
void __Dfs(int x,int brn){
rnk[x] = ++cnt;top[x] = brn;
if(son[x]) __Dfs(son[x],brn);
for(int i=head[x];i;i=nxt[i])
if(to[i] != son[x] && to[i] != ftr[x])
__Dfs(to[i],to[i]);
}
int Get(int x,int y){
int ans = -Inf;
while(top[x] != top[y]){
if(dpt[top[x]] > dpt[top[y]]) std :: swap(x,y);
ans = max(ans,Query(1,rnk[top[y]],rnk[y],1,n));
y = ftr[top[y]];
}
if(rnk[x] > rnk[y]) std :: swap(x,y);
if(x != y) ans = max(ans,Query(1,rnk[x]+1,rnk[y],1,n));
return ans;
}
}
using namespace Kruskal;
using namespace Segment_Tree;
using namespace Cute;
int main(){
scanf("%d%d%d",&n,&m,&t);
Rep( i , 1 , n ) fky[i] = i;
Rep( i , 1 , m ) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v);
std :: sort(a+1,a+m+1,cmp);
Rep( i , 1 , m ){
int u = find(a[i].x),v = find(a[i].y);
if(u != v){
Ins(a[i].x,a[i].y,a[i].v);
Ins(a[i].y,a[i].x,a[i].v);
fky[u] = v;
tot ++;
}
if(tot == n-1) break;
}
Dfs(1);__Dfs(1,1);
Rep( i , 1 , n ) modify(1,rnk[i],1,n,v[i]);
while( t-- ){
scanf("%d%d",&x,&y);
printf("%d\n",Get(x,y));
}
return 0;
}