bzoj3732
给你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点的所有路径中,最长的边最小值是多少?
Input
第一行: N, M, K。
第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。
第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
Output
对每个询问,输出最长的边最小值是多少。
Sample Input
6 6 8
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1
Sample Output
5
5
5
4
4
7
4
5
5
5
4
4
7
4
5
HINT
1 <= N <= 15,000
1 <= M <= 30,000
1 <= d_j <= 1,000,000,000
1 <= K <= 15,000
模拟一下样例,发现最小生成树贼有道理
然后倍增求树上最大值,感觉树剖也行
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define maxn 15005 #define maxm 30005 using namespace std; struct note{ int u,v,c; friend bool operator<(note a,note b) { return a.c<b.c; } }edge[maxm]; int to[maxm<<1],head[maxn],val[maxm<<1],next[maxm<<1]; int f[maxn][20],g[maxn][20],dep[maxn]; int rep[maxn]; int num,cnt,n,m,k; int getrep(int x) { if(rep[x]==x) return x; return rep[x]=getrep(rep[x]); } void dfs(int u,int fa) { for(int edge=head[u];edge;edge=next[edge]) { if(to[edge]==fa) continue; f[to[edge]][0]=u; g[to[edge]][0]=val[edge]; dep[to[edge]]=dep[u]+1; dfs(to[edge],u); } } void go_up(int &x,int c) { c=-c; for(int i=0;i<=19;i++) if(c&(1<<i)) cnt=max(cnt,g[x][i]),x=f[x][i]; } void make_lca() { for(int j=1;j<=19;j++) for(int i=1;i<=n;i++) { if(f[i][j-1]) { f[i][j]=f[f[i][j-1]][j-1]; g[i][j]=max(g[i][j-1],g[f[i][j-1]][j-1]); } else f[i][j]=0; } } int lca(int x,int y) { if(dep[x]>dep[y]) go_up(x,dep[y]-dep[x]); else go_up(y,dep[x]-dep[y]); if(x==y) return cnt; for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]) { cnt=max(cnt,max(g[x][i],g[y][i])); x=f[x][i];y=f[y][i]; } return max(cnt,max(g[x][0],g[y][0])); } void add(int u,int v,int c) { to[++num]=v; val[num]=c; next[num]=head[u]; head[u]=num; } int main() { scanf("%d %d %d",&n,&m,&k); for(int i=1;i<=m;i++) { scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].c); } sort(edge+1,edge+1+m); for(int i=1;i<=n;i++) rep[i]=i; for(int i=1;i<=m;i++) if(getrep(edge[i].u)!=getrep(edge[i].v)) { rep[getrep(edge[i].u)]=getrep(edge[i].v); add(edge[i].u,edge[i].v,edge[i].c); add(edge[i].v,edge[i].u,edge[i].c); } dfs(1,0); make_lca(); while(k--) { int x,y; scanf("%d %d",&x,&y); cnt=0; printf("%d\n",lca(x,y)); } return 0; }