消息传递 树形DP

非常妙的树形DP:由于n很小,我们可以枚举每一个点作为第一个节点,计算其时间花费

那么问题就转化为对于给点节点求花费时间。

通过观察,显然我们会发现先传给花费时间多的人更加合算,因为这样可以最大限度的避免

一个人还在辛苦的传递信息,另一个人却悠闲的喝下午茶(雾)的局面

所以我们可以每次都记录下对于一个节点而言,它的所有子节点的时长,

并对其排序,排序后先传给耗时最多的人,但这样传递了之后,由于耗时最多的人最先被传递,

那么这个本应耗时最多的人就不一定还是耗时最多的人了,因此我们要分别计算所有子节点

的耗时,并取max计入ans,最后dp数组即代表一旦这个节点得知消息,要多久才可以把消息传给 所有其他的人(除了传给它的那个人),即完成任务。树的结构保证了其正确性

why是ans=min(son[i]+cnt-i+1)?

因为这里为了方便是从小到大排序,又因为是优先大的

cnt-i即为还有多少个才能到它,然后+1是因为高斯这个点信息需要1的时间。

son[i]则是加上自身的时间

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define AC 1100
 4 #define ACway 2500
 5 #define R register int
 6 #define D printf("line in %d\n",__LINE__);
 7 int n;
 8 int Head[AC],Next[ACway],date[ACway],tot;
 9 int ans[AC],minn=INT_MAX,f[AC];//use用来存储每个节点的儿子(DFS中临时存储)
10 inline int read()
11 {
12     int x=0;char c;
13     while(isspace(c=getchar()));
14     while(c>='0' && c<='9')x=x*10+c-'0',c=getchar();
15     return x;
16 }
17 
18 inline void add(int f,int w)
19 {
20     date[++tot]=w , Next[tot]=Head[f] , Head[f]=tot;
21     date[++tot]=f , Next[tot]=Head[w] , Head[w]=tot; 
22 }   
23 
24 void upmax(int &a,int b)
25 {
26     if(b>a)a=b;
27 }
28 
29 void upmin(int &a,int b)
30 {
31     if(b<a)a=b;  
32 }
33 
34 void DFS(int x,int fa)
35 {
36     R now;
37     int cnt=0,son[AC];//开在DFS里面更加方便?
38     for(R i=Head[x]; i ;i=Next[i])//枚举子节点
39     {
40         now=date[i];
41         if(now!=fa)//如果不是父亲,即为儿子
42         {
43             DFS(now,x);
44             son[++cnt]=f[now];
45         }
46     }
47     sort(son+1,son+cnt+1);
48     for(R i=1;i<=cnt;i++) upmax(f[x],son[i]+cnt-i+1);
49 }
50 
51 void pre()
52 {
53     R a;
54     n=read();
55     for(R i=2;i<=n;i++)
56     {
57         a=read();//读入i的上级
58         add(a,i);
59     }
60 }
61 
62 void work()
63 {
64     for(R i=1;i<n;i++)//枚举第一个节点
65     {
66         memset(f,0,sizeof(f));
67         DFS(i,0);
68         ans[i]=f[i];//ans[i]存以i为第一个节点的最小耗时
69         upmin(minn,ans[i]);
70     }
71     printf("%d\n",minn+1);//还包括告诉别人的时间
72     for(R i=1;i<=n;i++) 
73         if(ans[i]==minn) printf("%d ",i);
74 }
75 
76 int main()
77 {
78 //  freopen("in.in","r",stdin);
79     pre();
80     work();
81 //  fclose(stdin);
82     return 0;
83 }

 

posted @ 2018-04-09 21:03  ww3113306  阅读(314)  评论(0编辑  收藏  举报
知识共享许可协议
本作品采用知识共享署名-非商业性使用-禁止演绎 3.0 未本地化版本许可协议进行许可。