51nod 1378 夹克老爷的愤怒(树型dp+贪心)

Posted 谦谦君子,陌上其华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1378 夹克老爷的愤怒(树型dp+贪心)相关的知识,希望对你有一定的参考价值。

 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1378

题意:

 

思路:
要想放得少,尽量放在叶子节点处,叶子节点处点比较多。

从叶子节点开始往上回溯,到第k个点时就放置一名家丁,用dp[x]来记录状态,若为负,则表示该节点及其子树所需要家丁的最远距离,若为正,则表示该节点及其子树中家丁还能镇压的最大距离。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 100000+5;
 6 const int inf = 0x3f3f3f3f;
 7 
 8 int n,k,tot,ans;
 9 int head[maxn],dp[maxn];
10 
11 struct node
12 {
13     int v,next;
14 }e[2*maxn];
15 
16 void addEdge(int u, int v)
17 {
18     e[tot].v = v;
19     e[tot].next = head[u];
20     head[u] = tot++;
21 }
22 
23 void dfs(int u, int fa)
24 {
25     int mi = inf;
26     int mx = -inf;
27     for(int i=head[u];i!=-1;i=e[i].next)
28     {
29         int v = e[i].v;
30         if(v == fa)  continue;
31         dfs(v,u);
32         mx = max(mx,dp[v]);
33         mi = min(mi,dp[v]);
34     }
35     if(mi == inf)  //叶子节点的情况
36     {
37         dp[u] = -1;
38     }
39     else if(mi <= -k)  //有节点超过k距离了,此时u必须要放置家丁
40     {
41         ans++;
42         dp[u] = k;
43     }
44     else if(mx+mi > 0)  //有节点能镇压住家丁
45     {
46         dp[u] = mx - 1;
47     }
48     else   //向上请求家丁
49         dp[u] = mi - 1;
50 }
51 
52 int main()
53 {
54     //freopen("in.txt","r",stdin);
55     scanf("%d%d",&n,&k);
56     tot = ans = 0;
57     memset(head,-1,sizeof(head));
58     for(int i=1;i<n;i++)
59     {
60         int u,v;
61         scanf("%d%d",&u,&v);
62         addEdge(u,v);
63         addEdge(v,u);
64     }
65     if(k==0)  {printf("%d\\n",n);return 0;}
66     dfs(0,-1);
67     if(dp[0]<0)  ans++;
68     printf("%d\\n",ans);
69     return 0;
70 }

 

以上是关于51nod 1378 夹克老爷的愤怒(树型dp+贪心)的主要内容,如果未能解决你的问题,请参考以下文章

51Nod 1378 夹克老爷的愤怒

51nod1380 夹克老爷的逢三抽一

51nod1625 夹克爷发红包(贪心+dfs)

51nod 1380 夹克老爷的逢三抽一 堆 脑洞题

51Nod 1380 夹克老爷的逢三抽一

51Nod1053 最大M子段和V2 二分+DP