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加成导致O(n)LCA乱搞也能AC……然后嘿嘿嘿
然后打了个奇丑无比倍增
维护两个数组anc[i,j]dis[i,j]分别表示i节点的2^j号祖先和i节点的与第2^j号祖先之间的路径最小值
接下来就和普通倍增没什么区别了,先把两个点调至同一深度,然后一起往上跳,跳的过程中记录答案

时间复杂度O(mlog2m+nlog2n+qlog2n)


树链剖分

树剖当然也能做啦!
把树剖分完以后,用线段树维护整一条重链的max
树剖LCA过程中查询线段树记录最大值
对于树剖来说这就是一道模板题

时间复杂度O(n+qlog22n)


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,倍增没有什么意义

原创粉丝点击