码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3732

时间:2018-10-28 16:15:41      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:lin   opera   zoj   using   [1]   tps   break   使用   分享图片   

转自hwzzyr的博客
kruskal重构树
技术分享图片
由于重构树中把原树的点权转换成为了新建节点的边权,这一过程是这样实现的。
首先对边排序
然后使用并查集辅助加边,每新建一条边时:
新建节点indexindex(编号从n+1n+1开始)
将原有两节点所在集合改为indexindex
将原有节点与indexindex连边
新建节点的权值为当前边的边权
给一下简单的代码

void Ex_Kruskal() {
    int ind=n,lim=n<<1; sort(e+1,e+1+m);
    for(int i=1;i<=lim;++i) f[i]=i;
    for(int i=1;i<=m;++i) {
        int fx=getfa(e[i].a),fy=getfa(e[i].b);
        if(fx!=fy) {
            f[fx]=f[fy]=++ind;
            val[ind]=e[i].w;
            add(ind,fx); add(ind,fy);
            if(ind==lim-1) break;
        }
    } return ;
}

代码复杂度很低,时间复杂度是优秀的O(nlog2n)

例题bzoj3732

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=3e4+2;
int n,m,q,cnt;
int fa[N<<1],f[N<<1][20],dep[N<<1],val[N<<1],g[N<<1][2];
int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
struct data{
    int u,v,w;
    bool operator<(const data &a)const{return w<a.w;}
}e[N<<1];
inline int ask(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    int t=dep[u]-dep[v];
    for(int i=0;i<20;i++)if(t&(1<<i))u=f[u][i];
    for(int i=19;~i;i--)if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
    if(u!=v)u=f[u][0];
    return u;
}
inline void dfs(int u){
    if(!g[u][0])return;
    dep[g[u][0]]=dep[g[u][1]]=dep[u]+1;
    dfs(g[u][0]),dfs(g[u][1]);
}
int main(){
    scanf("%d%d%d",&n,&m,&q),cnt=n;
    for(int i=0;i<m;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    sort(e,e+m);
    for(int i=1;i<=n;i++)fa[i]=i,fa[i+n]=i+n;
    for(int i=0;i<m;i++){
        int u=e[i].u,v=e[i].v;
        if(getfa(u)==getfa(v))continue;
        g[++cnt][0]=fa[u],g[cnt][1]=fa[v];
        fa[fa[u]]=fa[fa[v]]=f[fa[u]][0]=f[fa[v]][0]=cnt;
        val[cnt]=e[i].w;
    }
    dfs(cnt);
    for(int j=1;j<20;j++)
        for(int i=1;i<=cnt;i++)f[i][j]=f[f[i][j-1]][j-1];
    for(int x,y,i=0;i<q;i++){
        scanf("%d%d",&x,&y);
        printf("%d\n",val[ask(x,y)]);
    }
    return 0;
}

bzoj3732

标签:lin   opera   zoj   using   [1]   tps   break   使用   分享图片   

原文地址:https://www.cnblogs.com/MikuKnight/p/9865550.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!