Generator for Cactus
首先生成一棵树,然后对这棵树进行随机链剖分,处理出每个点对应的链顶。最后随机添加的非树边条数,随机一个点,若对应链顶没有被 作为链顶 被非树边连接过,则可以接受这一条非树边。
注意,这个版本是存在重边的,如果想去掉重边,再加个 \(\rm dep\) 数组判断即可。
# include <bits/stdc++.h>
using namespace std;
# define rg register
const int maxn=2e5+5;
bool vis[maxn];
int h[maxn],tot=1,x[maxn],y[maxn],tp[maxn];
struct edge { int to,nxt; } b[maxn<<1];
inline void add(rg int aa,rg int bb) {
b[tot].to=bb, b[tot].nxt=h[aa], h[aa]=tot++;
}
void dfs(rg int now,rg int lat) {
rg int jud=false;
for(rg int i=h[now]; ~i; i=b[i].nxt) {
rg int u=b[i].to; if(u==lat) continue;
if(!jud) tp[u]=tp[now], jud=true;
else tp[u]=u;
dfs(u,now);
}
}
int main() {
freopen("data.in","w",stdout);
memset(h,-1,sizeof(h));
mt19937 SEED(time(0));
uniform_int_distribution <int> makeNM(1,10);
int n=makeNM(SEED)+2, m=n-1;
rg int aa,bb; tp[1]=1;
for(rg int i=2;i<=n;++i) {
aa=rand()%(i-1)+1, bb=i;
x[i-1]=aa, y[i-1]=bb;
add(aa,bb), add(bb,aa);
}
dfs(1,0);
rg int cnt=makeNM(SEED)+1;
for(rg int i=1;i<=cnt;i++) {
aa=rand()%n+1; bb=tp[aa];
if(aa!=bb && !vis[bb]) {
x[++m]=aa, y[m]=bb;
vis[bb]=1;
}
}
printf("%d %d\n",n,m);
for(rg int i=1;i<=m;i++)
printf("%d %d\n",x[i],y[i]);
return 0;
}