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

  • 相关阅读:
    MQTT的优势
    http与https与tcp区别
    中科芯CKS-MBT30数据采集网关帮助工程师实现PLC远程上下载,减少出差成本
    CKS-MAT30远程程序上下载 支持欧姆龙西门子等PLC 远程下载、监控
    西门子S7以太网通讯协议
    DK云网关与普通DTU之间的区别
    腾讯笔试题
    二叉搜索树
    哈希,链接法解决冲突
    将16进制字符串转化为10进制数输出
  • 原文地址:https://www.cnblogs.com/passione-123456/p/12256774.html
Copyright © 2011-2022 走看看