zoukankan      html  css  js  c++  java
  • prufer序列

    生成树与prufer序列相互转换的模板:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=500010;
    struct node{
        int nxt,to;
    }e[N];
    int head[N],cnt,fa[N];
    int in[N],P;
    int deg[N],prufer[N],tot;
    int n;
    void add(int from,int to){
        e[++cnt].nxt=head[from];
        e[cnt].to=to;
        head[from]=cnt;
    }
    void dfs(int from,int F){
        fa[from]=F;
        if(F)deg[from]++;
        for(int i=head[from];i;i=e[i].nxt){
            int to=e[i].to;
            if(to==fa[from])continue;
            dfs(to,from);
            deg[from]++;
        }
    }
    void prufer_encode(){//得到序列长度和prufer序列
        memset(fa,0,sizeof fa);
        memset(prufer,0,sizeof prufer);
        memset(deg,0,sizeof deg);
        P=-1,tot=0;
        dfs(n,0);
        for(int i=1;i<=n;i++)in[i]=deg[i];
        for(int i=1;i<=n;i++)if(in[i]==1){P=i;break;}
        int now=P;
        for(int i=1;i<=n-2;i++){
            int nxt=fa[now];
            prufer[++tot]=nxt;
            if((--in[nxt])==1&&nxt<now){
                now=nxt;
            }else{
                P++;
                while(in[P]!=1)P++;
                now=P;
            }
        }
    }
    void prufer_decode(){//得到prufer序列对应原图以及各点度数
        memset(deg,0,sizeof deg);
        memset(head,0,sizeof head);
        memset(e,0,sizeof e);
        cnt=0,n=tot+2,P=-1;
        for(int i=1;i<=n;i++)deg[i]=1;
        for(int i=1;i<=tot;i++)deg[prufer[i]]++;
        for(int i=1;i<=n;i++)in[i]=deg[i];
        for(int i=1;i<=n;i++)if(in[i]==1){P=i;break;}
        int now=P;
        for(int i=1;i<=n-2;i++){
            int nxt=prufer[i];
            add(now,nxt);
            add(nxt,now);
            if((--in[nxt])==1&&nxt<now){
                now=nxt;
            }else{
                P++;
                while(in[P]!=1)P++;
                now=P;
            }
        }
        add(now,n);
        add(n,now);
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        prufer_encode();
        for(int i=1;i<=tot;i++){
            printf("%d ",prufer[i]);
        }
        puts("");
        prufer_decode();
        prufer_encode();
        for(int i=1;i<=tot;i++){
            printf("%d ",prufer[i]);
        }
        puts("");
    }
    prufer

    几条定理:

    1.Cayley定理:

      一个点数为n的完全图有nn-2个生成树

    2.一个n个点m条边的带标号无向图有k个连通块,我们希望添加k-1条边使图联通,求方案数:

      设第i个连通块的大小为si

      则答案为:

      

    以上具体证明见oiwiki

  • 相关阅读:
    数列分段divide
    精度计算(保留几位小数)
    洛谷P1119灾后重建
    暴雨rain
    石子游戏stone
    化学家chemist
    【ybtoj】【质数和约数】合并集合
    【ybtoj】【质数和约数】质数距离
    【ybtoj】【质数和约数】不定方程
    【再见OI】9.23模拟总结
  • 原文地址:https://www.cnblogs.com/passione-123456/p/12256774.html
Copyright © 2011-2022 走看看