求助(已解决):ccf csp树上搜索只得30分,想看看到底是哪里错。

原题链接: 202312-3 树上搜索

代码如下:(可能命名有些问题,但耐心读一读吧)

#include<iostream>
#include <stdlib.h>
using namespace std;


struct node{
int num;
long long food;//权重
long long w;//差值
int h;//是否移除
node** jk;
int body;
};


class tree{
long long beginall;//总权重
long long changeall;//动态总权重
int n;//编号
long long minw;
node* pp;

int alln;
long long* er;
int* yu;

node* now;
long long cv;//占总权值 

public:
	
void ert(){
	cv=0;
	changeall=beginall;
	n=-1;
	minw=-1;
	rebuild(pp);
}	


void rebuild(node* s){
	s->h=0;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		rebuild(*(p+i));
	}
	
}
	

void createtree(int a,long long* op,int* gh){
long long all=0;
for(int i=0;i<a;i++){
all=all+*(op+i);
}
beginall=all;
changeall=beginall;
n=-1;
minw=-1;

alln=a;
er=op;
yu=gh;

cv=0; 

pp=build(1);
}

node* build(int g){
node* s=new node;
s->num=g;
s->food=*(er+g-1);
s->w=-1;
s->h=0;
int ccall=0;
for(int i=0;i<alln-1;i++){
int b=*(yu+i);
if(b==g){ccall++;}
}
s->body=ccall;
if(s->body>0){
s->jk=new node*[s->body];
int io=0;
for(int i=0;i<alln-1;i++){
int b=*(yu+i);
if(b==g){
*(s->jk+io)=build(i+2);
io++;
}

}

}

return s;


}

int sdf(node* s,int x){
	if(s->h==0&&s->num==x){
		return 1;
	}
	if(s->h==0&&s->num!=x){
		int qwe=0;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		if(sdf(*(p+i),x)==1){
		qwe=1;
		break;
		}
	}
	return qwe;
	}
	if(s->h==1){
	return 0;
	}
}

void show(int x){
	node* cp=pp;
	while(true){
	select(cp);
	cout<<n<<" ";
	int ui=sdf(now,x);
	if(ui==1){cp=now;changeall=0;change(cp);n=-1;minw=-1;}
	else{action(now);n=-1;minw=-1;}
	number(cp);
	if(cv==1){cv=0;cout<<endl;break;}
	cv=0;
	}
}

void change(node* s){
	if(s->h==0){
	
    changeall=changeall+s->food;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		change(*(p+i));
	}
   }
}

void action(node* s){
    s->h=1;
    changeall=changeall-s->food;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		action(*(p+i));
	}
    
    

}

void number(node* s){
    if(s->h==0){cv++;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		node* cer=*(p+i);
		if(cer->h==0){
			cv++;break;
		}
	}
    }
    

}

long long getw(node* s){
	if(s->h==0){
	long long allnow=s->food;
	if(s->body==0){s->w=abs(changeall-allnow-allnow);return allnow;}
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		allnow=allnow+getw(*(p+i));
	}
	s->w=abs(changeall-allnow-allnow);
	return allnow;
	}
	else{return 0;}
}

void select(node* s){
	getw(s);
	selectnow(s);
}

void selectnow(node* s){
	if(s->h==0){
	if(minw==-1&&n==-1){
		n=s->num;
		minw=s->w;
		now=s;
	}
	else{
	
	if(s->w<minw){
		n=s->num;
		minw=s->w;
		now=s;
	}
	if(s->w==minw&&s->num<n){
		n=s->num;
		minw=s->w;
		now=s;
	
}
	
	}
	
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		selectnow(*(p+i));
	}
	
}


}

}; 

int main(){
int n,m;
cin>>n>>m;
long long* p=new long long[n];
int* cc=new int[n-1];
int* df=new int[m];
for(int i=0;i<n;i++){
long long b;
cin>>b;
*(p+i)=b;
}
for(int i=0;i<n-1;i++){
int b;
cin>>b;
*(cc+i)=b;
}
for(int i=0;i<m;i++){
int b;
cin>>b;
*(df+i)=b;
}

tree* tr=new tree;
tr->createtree(n,p,cc);
for(int i=0;i<m;i++){
tr->show(*(df+i));
tr->ert();
}
return 0;
}

真的很想知道哪里错了!!!拜谢!

---------------------------------------------------------------------------------------(分割线)

好吧,事实上,有一个逻辑错误,有一个离谱错误(找了2,3天了,在没发稿之前就在找)

逻辑错误:(action函数有误,会导致changeall多减,加个if就好)

void action(node* s){
	if(s->h==0){
	
    s->h=1;
    changeall=changeall-s->food;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		action(*(p+i));
	}
    
}

}

改后如下:

然后,重点来了,<stdlib.h>中abs()求绝对值不对long long有效?!!好吧,本来想省点事。。。

好吧,用if-else吧。

long long getw(node* s){
	if(s->h==0){
	long long allnow=s->food;
	if(s->body==0){
	long long cvbn=changeall-allnow-allnow;
	if(cvbn>=0){
		s->w=cvbn;
	}
	else{
		s->w=cvbn*-1;
	}
	return allnow;
	}
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		allnow=allnow+getw(*(p+i));
	}
	long long cvbn=changeall-allnow-allnow;
	if(cvbn>=0){
		s->w=cvbn;
	}
	else{
		s->w=cvbn*-1;
	}
	return allnow;
	}
	else{return 0;}
}

于是:(不放心,试了两遍)

nice!!!

完整代码如下:

#include<iostream>
using namespace std;


struct node{
int num;
long long food;//权重
long long w;//差值
int h;//是否移除
node** jk;
int body;
};


class tree{
long long beginall;//总权重
long long changeall;//动态总权重
int n;//编号
long long minw;
node* pp;

int alln;
long long* er;
int* yu;

node* now;
long long cv;

public:
	
void ert(){
	cv=0;
	changeall=beginall;
	n=-1;
	minw=-1;
	rebuild(pp);
}	


void rebuild(node* s){
	s->h=0;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		rebuild(*(p+i));
	}
	
}
	

void createtree(int a,long long* op,int* gh){
long long all=0;
for(int i=0;i<a;i++){
all=all+*(op+i);
}
beginall=all;
changeall=beginall;
n=-1;
minw=-1;

alln=a;
er=op;
yu=gh;

cv=0; 

pp=build(1);
}

node* build(int g){
node* s=new node;
s->num=g;
s->food=*(er+g-1);
s->w=-1;
s->h=0;
int ccall=0;
for(int i=0;i<alln-1;i++){
int b=*(yu+i);
if(b==g){ccall++;}
}
s->body=ccall;
if(s->body>0){
s->jk=new node*[s->body];
int io=0;
for(int i=0;i<alln-1;i++){
int b=*(yu+i);
if(b==g){
*(s->jk+io)=build(i+2);
io++;
}

}

}

return s;


}

int sdf(node* s,int x){
	if(s->h==0&&s->num==x){
		return 1;
	}
	if(s->h==0&&s->num!=x){
		int qwe=0;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		if(sdf(*(p+i),x)==1){
		qwe=1;
		break;
		}
	}
	return qwe;
	}
	if(s->h==1){
	return 0;
	}
}

void show(int x){
	node* cp=pp;
	while(true){
	select(cp);
	cout<<n<<" ";
	int ui=sdf(now,x);
	if(ui==1){cp=now;changeall=0;change(cp);n=-1;minw=-1;}
	else{action(now);n=-1;minw=-1;}
	number(cp);
	if(cv==1){cv=0;cout<<endl;break;}
	cv=0;
	}
}

void change(node* s){
	if(s->h==0){
	
    changeall=changeall+s->food;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		change(*(p+i));
	}
   }
}

void action(node* s){
	if(s->h==0){
	
    s->h=1;
    changeall=changeall-s->food;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		action(*(p+i));
	}
    
}

}

void number(node* s){
    if(s->h==0){cv++;
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		node* cer=*(p+i);
		if(cer->h==0){
			cv++;break;
		}
	}
    }
    

}

long long getw(node* s){
	if(s->h==0){
	long long allnow=s->food;
	if(s->body==0){
	long long cvbn=changeall-allnow-allnow;
	if(cvbn>=0){
		s->w=cvbn;
	}
	else{
		s->w=cvbn*-1;
	}
	return allnow;
	}
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		allnow=allnow+getw(*(p+i));
	}
	long long cvbn=changeall-allnow-allnow;
	if(cvbn>=0){
		s->w=cvbn;
	}
	else{
		s->w=cvbn*-1;
	}
	return allnow;
	}
	else{return 0;}
}

void select(node* s){
	getw(s);
	selectnow(s);
}

void selectnow(node* s){
	if(s->h==0){
	if(minw==-1&&n==-1){
		n=s->num;
		minw=s->w;
		now=s;
	}
	else{
	
	if(s->w==minw&&s->num<n){
		n=s->num;
		minw=s->w;
		now=s;
	
}
	
	
	
	if(s->w<minw){
		n=s->num;
		minw=s->w;
		now=s;
	}
	
	}
	
	for(int i=0;i<s->body;i++){
		node** p=s->jk;
		selectnow(*(p+i));
	}
	
}


}

}; 

int main(){
int n,m;
cin>>n>>m;
long long* p=new long long[n];
int* cc=new int[n-1];
int* df=new int[m];
for(int i=0;i<n;i++){
long long b;
cin>>b;
*(p+i)=b;
}
for(int i=0;i<n-1;i++){
int b;
cin>>b;
*(cc+i)=b;
}
for(int i=0;i<m;i++){
int b;
cin>>b;
*(df+i)=b;
}


tree* tr=new tree;
tr->createtree(n,p,cc);
for(int i=0;i<m;i++){
tr->show(*(df+i));
tr->ert();
}

    delete[] p;
    delete[] cc;
    delete[] df;
    delete tr;


return 0;
}

没想到最终还是自己搞出来的,唉,记录一下,警告自己,下次一定要注意!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值