BZOJ 3732 Network Kruskal重构树

来源:互联网 发布:新一代人工智能发展 编辑:程序博客网 时间:2024/06/08 09:05

题目大意:给定一个n个点m条边的无向连通图,k次询问两点之间所有路径中最长边的最小值

Kruskal+倍增LCA做法见http://blog.csdn.net/popoqqq/article/details/39755703

LCT做法见http://blog.csdn.net/popoqqq/article/details/39929277

Kruskal重构树真是强大……一不小心手滑就RANK1啥的……

每加入一条边时,我们并不链接这条边的两端点,而是把这条边两端点所在并查集的根连接起来,而且是按秩合并

这样做的好处就是任何一个节点到根的路径长度不超过logn

且由于Kruskal重构树的性质,两点之间的最长边和原图相同,且最长边的一端连接的一定是两点的LCA

于是直接暴力向上找就行 如果加上倍增的话或许能优化到O(loglogn)

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 15100using namespace std;struct abcd{    int x,y,f;    bool operator < (const abcd &Y) const    {        return f < Y.f ;    }}edges[M<<1];int n,m,k;int belong[M],fa[M],size[M],dis[M],dpt[M];int Find(int x){    if(!belong[x])        belong[x]=x,size[x]=1;    if(belong[x]==x)        return x;    return belong[x]=Find(belong[x]);}int Get_Depth(int x){    if(dpt[x]) return dpt[x];    if(!fa[x]) return dpt[x]=1;    return dpt[x]=Get_Depth(fa[x])+1;}void Kruskal(){    int i;    sort(edges+1,edges+m+1);    for(i=1;i<=m;i++)    {        int x=Find(edges[i].x);        int y=Find(edges[i].y);        if(x==y) continue ;        if(size[x]>size[y])            swap(x,y);        belong[x]=y;        size[y]=max(size[y],size[x]+1);        fa[x]=y;        dis[x]=edges[i].f;    }}int Query(int x,int y){    int re=0;    if(dpt[x]<dpt[y])        swap(x,y);    while(dpt[x]>dpt[y])        re=max(re,dis[x]),x=fa[x];    while(x!=y)        re=max(re,dis[x]),re=max(re,dis[y]),x=fa[x],y=fa[y];    return re;}int main(){    int i,x,y;    cin>>n>>m>>k;    for(i=1;i<=m;i++)        scanf("%d%d%d",&edges[i].x,&edges[i].y,&edges[i].f);    Kruskal();    for(i=1;i<=n;i++)        Get_Depth(i);    for(i=1;i<=k;i++)    {        scanf("%d%d",&x,&y);        printf("%d\n", Query(x,y) );    }}


0 0
原创粉丝点击