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

原文地址:https://www.cnblogs.com/passione-123456/p/12256774.html