JZOJsenior1738.Heatwave
来源:互联网 发布:笔记本网络初始化失败 编辑:程序博客网 时间:2024/05/22 04:44
problem
Description
给你N个点的无向连通图,图中有M条边,第j条边的长度为: d_j.
现在有 K个询问。
每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
Input
文件名为heatwave.in
第一行: 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
Sample Output
5
5
5
4
4
7
4
5
Data Constraint
50% 1<=N,M<=3000 其中30% K<=5000
100% 1 <= N <= 15,000 1 <= M <= 30,000 1 <= d_j <= 1,000,000,000 1 <= K <= 20,000
Hint
analysis
既然题目要求两点间最长边的最小值,那么我们就把这幅图的MST先求出来
这样两点间一定联通且满足两点间最长边最小(没有为什么自己想一想因为这点比较明显)
MST用kruskal求,比较基础,我就当你会了
求完MST之后把整棵树遍历一次,求出每个点的深度
树上倍增
(这题的JZ数据buff加成导致然后嘿嘿嘿)
然后打了个奇丑无比的倍增
维护两个数组
接下来就和普通倍增没什么区别了,先把两个点调至同一深度,然后一起往上跳,跳的过程中记录答案
时间复杂度
树链剖分
树剖当然也能做啦!
把树剖分完以后,用线段树维护整一条重链的
树剖求对于树剖来说这就是一道模板题
时间复杂度
code
树上倍增code(50+ms)
var a,edge:array[0..15000]of array of longint; anc,dis:array[0..15000,0..15]of longint; b:array[0..30000,0..3]of longint; depth,father:array[0..15000]of longint; n,m,q,i,j,x,y:longint;function max(x,y:longint):longint;begin if x>y then exit(x); exit(y);end;procedure swap(var x,y:longint);var z:longint;begin z:=x; x:=y; y:=z;end;procedure qsort(l,r:longint);var i,j,mid:longint;begin i:=l; j:=r; mid:=b[(l+r)div 2,3]; repeat while b[i,3]<mid do inc(i); while b[j,3]>mid do dec(j); if i<=j then begin b[0]:=b[i]; b[i]:=b[j]; b[j]:=b[0]; inc(i); dec(j); end; until i>j; if l<j then qsort(l,j); if i<r then qsort(i,r);end;function getfather(x:longint):longint;begin if father[x]=x then exit(x); father[x]:=getfather(father[x]); exit(father[x]);end;procedure dfs(x,y:longint);var i:longint;begin for i:=1 to a[x,0] do if a[x,i]<>y then begin anc[a[x,i],0]:=x; depth[a[x,i]]:=depth[x]+1; dis[a[x,i],0]:=edge[x,i]; dfs(a[x,i],x); end;end;function lca(x,y:longint):longint;var k:longint;begin lca:=0; if depth[x]<depth[y] then swap(x,y); k:=trunc(ln(depth[x]-depth[y]+1)/ln(2)); while k>=0 do begin if depth[anc[x,k]]>depth[y] then begin lca:=max(lca,dis[x,k]); x:=anc[x,k]; end; dec(k); end; if depth[x]<>depth[y] then begin lca:=max(lca,dis[x,0]); x:=anc[x,0]; end; k:=trunc(ln(depth[x])/ln(2)); while k>=0 do begin if anc[x,k]<>anc[y,k] then begin lca:=max(max(lca,dis[x,k]),dis[y,k]); x:=anc[x,k]; y:=anc[y,k]; end; dec(k); end; if x=y then exit(lca); exit(max(lca,max(dis[x,0],dis[y,0])));end;begin readln(n,m,q); for i:=1 to n do begin father[i]:=i; setlength(a[i],1); a[i,0]:=0; setlength(edge[i],1); edge[i,0]:=0; end; for i:=1 to m do begin for j:=1 to 3 do read(b[i,j]); readln; end; qsort(1,m); for i:=1 to m do begin x:=b[i,1]; y:=b[i,2]; if getfather(x)<>getfather(y)then begin father[getfather(x)]:=getfather(y); inc(a[x,0]); setlength(a[x],a[x,0]+1); a[x,a[x,0]]:=y; inc(edge[x,0]); setlength(edge[x],edge[x,0]+1); edge[x,a[x,0]]:=b[i,3]; inc(a[y,0]); setlength(a[y],a[y,0]+1); a[y,a[y,0]]:=x; inc(edge[y,0]); setlength(edge[y],edge[y,0]+1); edge[y,a[y,0]]:=b[i,3]; end; end; depth[1]:=1; dfs(1,0); for j:=1 to trunc(ln(n)/ln(2)) do for i:=1 to n do begin anc[i,j]:=anc[anc[i,j-1],j-1]; dis[i,j]:=max(dis[i,j-1],dis[anc[i,j-1],j-1]); end; for i:=1 to q do begin readln(x,y); writeln(lca(x,y)); end;end.
var b,c,next,last,father,size:array[0..80000]of longint; anc,dis:array[0..15000,0..16]of longint; a:array[0..30000,1..3] of longint; n,m,i,j,k,x,y,tot:longint;procedure swap(var x,y:longint);var z:longint;begin z:=x; x:=y; y:=z;end;function max(x,y:longint):longint;begin if x>y then exit(x); exit(y);end;procedure qsort(l,r:longint);var i,j,mid:longint;begin i:=l; j:=r; mid:=a[(l+r)div 2,3]; repeat while a[i,3]<mid do inc(i); while a[j,3]>mid do dec(j); if i<=j then begin a[0]:=a[i]; a[i]:=a[j]; a[j]:=a[0]; inc(i); dec(j); end; until i>j; if l<j then qsort(l,j); if i<r then qsort(i,r);end;function getfather(k:longint):longint;begin if father[k]=0 then exit(k); father[k]:=getfather(father[k]); exit(father[k]);end;function judge(x,y:longint):boolean;begin exit(getfather(x)=getfather(y));end;procedure insert(x,y,z:longint);begin inc(tot); b[tot]:=y; next[tot]:=last[x]; last[x]:=tot; c[tot]:=z;end;procedure dfs(x,y:longint);var now:longint;begin now:=last[x]; while now<>0 do begin if b[now]<>y then begin anc[b[now],0]:=x; size[b[now]]:=size[x]+1; dis[b[now],0]:=c[now]; dfs(b[now],x); end; now:=next[now]; end;end;function lca(x,y:longint):longint;var k:longint;begin lca:=0; if size[x]<size[y] then swap(x,y); k:=trunc(ln(size[x]-size[y]+1)/ln(2)); while k>=0 do begin if size[anc[x,k]]>size[y] then begin lca:=max(lca,dis[x,k]); x:=anc[x,k]; end; dec(k); end; if size[x]<>size[y] then begin lca:=max(lca,dis[x,0]); x:=anc[x,0]; end; k:=trunc(ln(size[x])/ln(2)); while k>=0 do begin if anc[x,k]<>anc[y,k] then begin lca:=max(max(lca,dis[x,k]),dis[y,k]); x:=anc[x,k]; y:=anc[y,k]; end; dec(k); end; if x=y then exit(lca); exit(max(lca,max(dis[x,0],dis[y,0])));end;begin assign(input,'readin.pas');reset(input); readln(n,m,k); for i:=1 to m do readln(a[i,1],a[i,2],a[i,3]); qsort(1,m); for i:=1 to m do begin if (not judge(a[i,1],a[i,2])) then begin insert(a[i,1],a[i,2],a[i,3]); insert(a[i,2],a[i,1],a[i,3]); father[getfather(a[i,1])]:=getfather(a[i,2]); end; end; size[1]:=1; dfs(1,0); for j:=1 to trunc(ln(n)/ln(2)) do for i:=1 to n do begin anc[i,j]:=anc[anc[i,j-1],j-1]; dis[i,j]:=max(dis[i,j-1],dis[anc[i,j-1],j-1]); end; for i:=1 to k do begin readln(x,y); writeln(lca(x,y)); end;end.
树链剖分code(44ms)
#include<cstdio>#include<algorithm>#define MAXN 15001#define INF 1000000007using namespace std;int last[4*MAXN],next[4*MAXN],tov[4*MAXN],dis[4*MAXN];int to_num[4*MAXN],father[MAXN];int n,m,k,tot,total;struct information{ int depth,father,size,heavy_son,top,to_tree,value;}a[4*MAXN];struct point{ int mx,ans;}tree[4*MAXN];struct dist{ int u,v,w;}line[4*MAXN];bool cmp(dist a,dist b){ return a.w<b.w;}int getfather(int x){ if (father[x]==0)return x; father[x]=getfather(father[x]); return father[x];}void insert(int x,int y,int z){ next[++tot]=last[x]; last[x]=tot; tov[tot]=y; dis[tot]=z;}void dfs1(int x,int father){ int mx=-1; a[x].size=1; for (int i=last[x];i;i=next[i]) { int j=tov[i]; if (j!=father) { a[j].depth=a[x].depth+1; a[j].father=x; a[j].value=dis[i]; dfs1(j,x); a[x].size+=a[j].size; if (a[j].size>mx) { mx=a[j].size; a[x].heavy_son=j; } } }}void dfs2(int x,int father,int top){ if (x==0)return; a[x].top=top; a[x].to_tree=++total; to_num[total]=x; dfs2(a[x].heavy_son,x,top); for (int i=last[x];i;i=next[i]) { int j=tov[i]; if (j!=father && j!=a[x].heavy_son && j!=0) { dfs2(j,x,j); } }}void maketree(int t,int l,int r){ if (l==r) { tree[t].mx=a[to_num[l]].value; return; } int mid=(l+r)/2; maketree(t*2,l,mid); maketree(t*2+1,mid+1,r); tree[t].mx=max(tree[t*2].mx,tree[t*2+1].mx);}int tree_query_max(int t,int l,int r,int x,int y){ if (l==x && r==y) { return tree[t].mx; } int mid=(l+r)/2; if (y<=mid) { return tree_query_max(t*2,l,mid,x,y); } else if (x>mid) { return tree_query_max(t*2+1,mid+1,r,x,y); } else return max(tree_query_max(t*2,l,mid,x,mid),tree_query_max(t*2+1,mid+1,r,mid+1,y));}int query_max(int x,int y){ int temp=-1; while (a[x].top!=a[y].top) { if (a[a[x].top].depth>a[a[y].top].depth) { temp=max(temp,tree_query_max(1,1,n,a[a[x].top].to_tree,a[x].to_tree)); x=a[a[x].top].father; } else { temp=max(temp,tree_query_max(1,1,n,a[a[y].top].to_tree,a[y].to_tree)); y=a[a[y].top].father; } } if (x==y)return temp; if (a[x].depth<a[y].depth) { temp=max(temp,tree_query_max(1,1,n,a[a[x].heavy_son].to_tree,a[y].to_tree)); } else { temp=max(temp,tree_query_max(1,1,n,a[a[y].heavy_son].to_tree,a[x].to_tree)); } return temp;}int main(){ //freopen("readin.txt","r",stdin); scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=m;i++) { scanf("%d%d%d",&line[i].u,&line[i].v,&line[i].w); } sort(line+1,line+m+1,cmp); for (int i=1;i<=m;i++) { if (getfather(line[i].u)!=getfather(line[i].v)) { father[getfather(line[i].u)]=getfather(line[i].v); insert(line[i].u,line[i].v,line[i].w); insert(line[i].v,line[i].u,line[i].w); } } a[1].depth=1; dfs1(1,0),dfs2(1,0,1); maketree(1,1,n); for (int i=1;i<=k;i++) { int x,y; scanf("%d%d",&x,&y); printf("%d\n",query_max(x,y)); } return 0;}
不过其实对于随机数据的LCA,倍增没有什么意义
- JZOJsenior1738.Heatwave
- Heatwave
- JZOJ1738. Heatwave
- 1738. Heatwave
- jzoj1738. Heatwave
- <最小生成树><lca>Heatwave
- ssl2779 Heatwave 最小生成树+倍增
- 2017.10.07【NOIP提高组】模拟赛B组 Heatwave 题解
- SSL2779 2017年10月21日提高组 Heatwave(lca+rmq)
- 全栈者角度的前端整理
- 设计模式-结构型-桥接
- Codeforces 869 C. The Intriguing Obsession (组合数学)
- Django视图 view
- 第九章 浮动
- JZOJsenior1738.Heatwave
- 传返回值给CrimeListFragment+修改列表项
- 134. Gas Station
- map用法
- Linux查找命令小结
- 偷懒的西西【推荐】
- python3队列及循环队列基本实现
- STM32开发环境搭建
- Java中static关键词的作用