数据结构数据生成器--生成树 bzoj1036

来源:互联网 发布:数据修炼系统 编辑:程序博客网 时间:2024/05/20 23:37

今天写了一道数据结构的经典题---树的统计,尝试用LCT写,结果不造怎的可以过样例,但交上去就WA,苦于肉眼找不出错,于是翻出了以前写的树立剖分的版本,想来搞搞对拍。

然而~~~~~尼玛树怎么构造啊- -


然后沉思- -,网上搜索,找不到- - -- - - - -- - - - 


然后想起来了purfer编码,咦,purfer编码不就是搞树的么。

还记得purfer编码是可以把一棵树转成purfer编码的,而且也可以由purfer编码转成树!


先把purfer编码中每个数出现一次就把度数+1(初始化每个点度数为1)


然后顺序枚举purfer编码的每一个i,在度数表里面找度数为1的编号最小的那一个,把当前i和度数表里面标号最小的那个度数同时-1,然后这两个点之间连边.

(有没有可能自己和自己连边呢?我也考虑过,结果发现自己太蠢了:   自己和自己连边说明purfer编码里面有一个自己,它的度至少为2,这样在度数表里面不可能选到它,就矛盾了,所以这个想法是不成立的)


然后最后会剩下两个度数为1的点,他们之间再连一条边就好了。

这样,一棵树就形成了、


为了操作方便,我使用了结构体,随时排序,找编号和找度数为1且编号最小的点:

(可能有点慢)核心部分在主函数里面

makedata   bzoj1036

#include<cstdio>#include<iostream>#include<ctime>#include<cstdlib>#include<algorithm>using namespace std;int a[30000+20];struct nod{int id,d;}d[30000+20];bool cmpid(nod x,nod y)//按编号排序{return x.id<y.id;}bool cmp(nod x,nod y)//按度数排序{if(x.d!=y.d)return x.d<y.d;else return x.id<y.id;}int main(){freopen("1.in","w",stdout);srand(time(NULL));int n=rand()%10+1;cout<<n<<endl;for(int i=1;i<=n;i++){d[i].d=1;d[i].id=i;}for(int i=1;i<=n-2;i++)a[i]=rand()%n+1;//生成purfer编码for(int i=1;i<=n-2;i++)d[a[i]].d++;//累加度数for(int i=1;i<=n-2;i++){sort(d+1,d+n+1,cmp);int j;for(j=1;j<=n;j++)if(d[j].d)break;printf("%d %d\n",d[j].id,a[i]);d[j].d--;sort(d+1,d+n+1,cmpid);d[a[i]].d--;}                                //模拟上述过程,找度数为1且编号最小的和purfer编码中当前位sort(d+1,d+n+1,cmp);printf("%d %d\n",d[n-1].id,d[n].id);//最后两个点之间连边for(int i=1;i<=n;i++){printf("%d ",(rand()%20)-10);}int m=rand()%20+1;cout<<endl;cout<<m<<endl;for(int i=1;i<=m;i++){int s=rand()%3+1;if(s==1)printf("QMAX ");if(s==2)printf("QSUM ");if(s==3)printf("CHANGE ");int a=rand()%n+1;int b=rand()%a+1;while(a==b){a=rand()%n+1;    b=rand()%a+1;}cout<<a<<" "<<b<<endl;}return 0;}

有了这个数据生成器,就可以对拍了,然后就找出错,发现自己萌的可爱- -

错误点:max的初始化为0,结果权值可能为负,一求max就变成了0,就WA了。


0 0