bzoj 2783 //2783: [JLOI2012]树 //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=2783
更多题解,详见https://blog.csdn.net/mrcrack/article/details/90228694BZOJ刷题记录
方法一:dfs 深搜+剪枝 技术含量低,但掌握不易:
2776 kb | 368 ms | C++/Edit | 726 B |
//2783: [JLOI2012]树
//在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=2783
//看来半天,文不对题,看到后面才发现,之前内容无用,题目才刚刚开始
//简单画了图,题意弄明白了。
//n=100000,s=1000,10^5*10^3=10^8 int不会溢出。
//此文https://www.luogu.org/problemnew/solution/P3252 作者: enceladus 更新时间: 2018-09-04 10:43 思路写得不错,摘抄如下
//样例通过,提交AC.2019-10-27 22:20
//回过头想了想,深搜的技术含量是比较低,但能编得好的又有几人呢。
#include
#include
#define maxn 100010
int n,s,head[maxn],cnt=0,w[maxn],fa[maxn],ans=0;
struct node{
int to,next;
}e[maxn];
void add_edge(int u,int v){
cnt++,e[cnt].to=v,e[cnt].next=head[u],head[u]=cnt;
}
void dfs(int x,int d){
int b,v;
if(d>s)return;
if(d==s)ans++;
for(b=head[x];b;b=e[b].next){
v=e[b].to;
if(v!=fa[x])
dfs(v,d+w[v]);
}
}
int main(){
int i,x,y;
memset(head,0,sizeof(head));
scanf("%d%d",&n,&s);
for(i=1;i<=n;i++)scanf("%d",&w[i]);
for(i=1;i
add_edge(x,y),fa[y]=x;
}
for(i=1;i<=n;i++)dfs(i,w[i]);
printf("%d\n",ans);
return 0;
}
方法二:树上倍增
18524 kb | 496 ms | C++/Edit | 1032 B |
//树上倍增,核心就是+,2^j-1+2^j-1=2^j
//log10^5=17
//此文https://www.luogu.org/problemnew/solution/P3252?page=3 作者: _OiNksEduCn_ 更新时间: 2019-08-25 16:46代码写得不错,思路写得不错。
/*
*/
//样例通过,提交AC.2019-10-30 19:16
#include
#include
#define maxn 100100
int fa[maxn][20],w[maxn][20],n,s,head[maxn],cnt=0,ans=0;
struct node{
int to,next;
}e[maxn];
void add_edge(int u,int v){
cnt++,e[cnt].to=v,e[cnt].next=head[u],head[u]=cnt;
}
void dfs(int x,int father){
int i,j,b,v,now,p;
fa[x][0]=father;//漏了此句
for(i=1;i<=17;i++){
fa[x][i]=fa[fa[x][i-1]][i-1];
w[x][i]=w[x][i-1]+w[fa[x][i-1]][i-1];
}
now=s,p=x;
for(i=17;i>=0;i--)
if(fa[p][i]&&now>w[p][i])
now-=w[p][i],p=fa[p][i];//此处错写成now-=w[p][i],p=fa[p][i-1];
if(now==w[p][0])ans++;//此处错写成if(now=w[p][0])ans++;这种昏招都有
for(b=head[x];b;b=e[b].next){
v=e[b].to;
if(v!=father)
dfs(v,x);
}
}
int main(){
int i,u,v;
memset(head,0,sizeof(head));
scanf("%d%d",&n,&s);
for(i=1;i<=n;i++)scanf("%d",&w[i][0]);
for(i=1;i
printf("%d\n",ans);
return 0;
}