对拍-随机树生成O(n)

对拍用的,思路很简单。
用并查集维护这棵树。
考虑以1为根节点,那么我们只要对于n到2的每一个节点i,让random(1,i-1)为它的根,可以保证这样不会成环且连通。
如果不要求一定以1为根节点

  • 一种方法是,我们可以认为构造的这棵树为无根树,然后换根输出就好。
  • 另一种方法就是下面写的用random_shuffle函数获得一个随机的1~n的排列,然后对应着输出就好。

都是O(n)

//随机树生成O(n)
#include<bits/stdc++.h>
using namespace std;
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
typedef long long ll;
typedef unsigned long long ull;

stringstream ss;

int dsu[1000005];//1e6
int mapp[10000005];

void create(){
    int n=random(1,10);
    for(int i=n;i>=2;--i){
        dsu[i]=random(1,i-1);//生成一颗以1为根节点的树
    }
    //以上为以1为根,随机还要重新编号对应一下,可以借助随机乱序函数
    for(int i=1;i<=n;++i) mapp[i]=i;
    random_shuffle(mapp+1,mapp+n+1);//随机排列  
    //打印树,必要可以随机边权
    printf("%d\n",n);
    for(int i=2;i<=n;++i){
        printf("%d %d\n",mapp[i],mapp[ dsu[i] ]);
    }
    return;
}

int main()
{
    //IOS;
    srand(time(NULL));
    int t=1;
    while(t--) create();
    return 0;
}
posted @ 2021-08-06 14:03  七铭的魔法师  阅读(119)  评论(0编辑  收藏  举报