题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805059118809088
题意:给定n个人,编号0~n-1,0为祖先,每个人有一个师傅,每次从师傅传功夫到徒弟时,功力值会削弱r,但可能会出现得道者,功力翻n倍,计算所有得道者功力值之和。
思路:因为计算功力值时要从祖先开始逐渐向下计算,所以我们需要存储每个人的徒弟,然后从上向下遍历即可,我这里用的是邻接表实现的,定义maxn个表头结点head,head[i]其中包括它的第一个徒弟编号nxt,翻的倍数,功力值;定义maxn个表结点,指向其兄弟结点。然后用dfs从祖先编号0开始搜即可,但我被两个细节点卡了一个多小时,卡到崩溃QAQ:1.输入的r是[0,100]的值,还需除100; 2. 我写代码没带脑子,在dfs函数中用全局变量tmp作为指向徒弟的指针,然后程序一直在那运行错误的结果...
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=100005; 5 struct node{ 6 int nxt,bg; 7 double gl; 8 }head[maxn]; 9 10 int n,k,tmp,nxt[maxn]; 11 double z,r,sum; 12 13 void dfs(int p){ 14 if(head[p].bg) 15 sum+=head[p].gl*head[p].bg; 16 else{ 17 int t=head[p].nxt; 18 while(t){ 19 head[t].gl=head[p].gl*r; 20 dfs(t); 21 t=nxt[t]; 22 } 23 } 24 } 25 26 int main(){ 27 scanf("%d%lf%lf",&n,&z,&r); 28 r=1.0-0.01*r; 29 head[0].gl=z; 30 for(int i=0;i<n;++i){ 31 scanf("%d",&k); 32 if(!k) 33 scanf("%d",&head[i].bg); 34 else 35 while(k--){ 36 scanf("%d",&tmp); 37 nxt[tmp]=head[i].nxt; 38 head[i].nxt=tmp; 39 } 40 } 41 dfs(0); 42 printf("%lld ",(long long)sum); 43 return 0; 44 }