将军令(贪心&&树形DP)

只看45分的话,是树形DP....(当然也有能拿到70分+的大佬)

40分:

只考虑k==1的情况,树形DP

所以每个节点可能被父亲,自己,儿子控制

设f[MAXN][3],0表示儿子,1表示自己,2表示父亲

f[i][1]+=min(f[to][0],f[to][1],f[to][2])(因为自己控制自己,儿子怎样都行)

f[i][0]+=min(f[to][0],f[to][1])

但是因为i的儿子必须有一个自己控制自己,所以还要判断所加值中是否有f[to][1],如果没有

f[i][0]+=min(f[to][1]-f[to][0])

f[i][2]+=min(f[to][1],f[to][0])

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<map>
 6 #include<vector>
 7 #include<set>
 8 #include<cmath>
 9 #define MAXN 600001
10 #define int long long
11 using namespace std;
12 struct node{int to,n;}e[MAXN*2];
13 int head[MAXN],tot;
14 void add(int u,int v)
15 {
16      e[++tot].to=v;e[tot].n=head[u];head[u]=tot;
17 }
18 int read()
19 {
20     int x=0;char c=getchar();
21     while(c<'0'||c>'9')c=getchar();
22     while(c>='0'&&c<='9')
23     {
24         x=(x<<1)+(x<<3)+(c^48);
25         c=getchar();
26     }
27     return x;
28 }
29 int f[MAXN][4];//0 儿子 1 自己 2 父亲
30 void DFS(int x,int fa)
31 {
32     int ok=1,minn=100000;
33     f[x][1]=1;
34     for(int i=head[x];i;i=e[i].n)
35     {
36         int to=e[i].to;
37         if(to==fa)continue;
38         DFS(to,x);
39         if(f[to][1]<=f[to][0])
40         {
41            f[x][0]+=f[to][1];
42            ok=0;
43         }
44         else f[x][0]+=f[to][0];
45         f[x][1]+=min(f[to][1],min(f[to][2],f[to][0]));
46         f[x][2]+=min(f[to][1],f[to][0]);
47     }
48     if(ok==1)
49     {
50        for(int i=head[x];i;i=e[i].n)
51        {
52            int to=e[i].to;
53            if(to==fa)continue;
54            minn=min(minn,f[to][1]-f[to][0]);
55        }
56        f[x][0]+=minn;
57     }    
58 }
59 int n,k,t;
60 signed main()
61 {
62     n=read();k=read();t=read();
63     for(int i=1;i<=n-1;++i)
64     {
65         int x,y;
66         x=read();y=read();
67         add(x,y);add(y,x);
68     }
69     if(k==0)
70     {
71        printf("%lld\n",n);
72        return 0;
73     }
74     DFS(1,0);
75     printf("%lld\n",min(f[1][1],f[1][0]));
76 }
45分

100分

贪心很好想吧.....

每次选出深度最大的节点,找到他的第k级祖先,然后暴力修改他的k距离范围内的点

正确性的话,我们每次恰好选k级祖先(或根),对于覆盖范围来说,肯定比k级祖先的父亲和儿子要好啦啦.....

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<map>
 6 #include<vector>
 7 #include<set>
 8 #include<algorithm>
 9 #include<cmath>
10 #include<queue>
11 #define MAXN 1000001
12 using namespace std;
13 struct node{int to,n;}e[MAXN*2];
14 int n,k,t;
15 int head[MAXN],tot=0;
16 int read()
17 {
18      char c=getchar();int x=0;
19      while(c<'0'||c>'9')c=getchar();
20      while(c>='0'&&c<='9')
21      {
22           x=(x<<1)+(x<<3)+(c^48);
23           c=getchar();
24      } 
25      return x;
26 }
27 void add(int u,int v)
28 {
29      e[++tot].to=v;e[tot].n=head[u];head[u]=tot;
30 }
31 priority_queue<pair<int,int> >q;
32 int fa[MAXN];
33 int deep[MAXN];
34 void DFS(int x,int faa)
35 {        
36      q.push(make_pair(deep[x],x));
37      for(int i=head[x];i;i=e[i].n)
38      {
39          int to=e[i].to;
40          if(faa==to)continue;
41          fa[to]=x;
42          deep[to]=deep[x]+1;
43          DFS(to,x);
44      }
45 }
46 bool vis[MAXN];
47 int find(int x,int kk)
48 {
49     if(deep[x]<=kk)return 1;
50     while(kk!=0)
51     {
52         kk--;
53         x=fa[x];  
54     }
55     return x;
56 }
57 void check(int x,int faa,int root,int kx)
58 {
59      if(kx>k)return ;
60      vis[x]=1;
61      //printf("vis[%d]=%d deep[%d]=%d\n",x,vis[x],root,deep[root]);
62      for(int i=head[x];i;i=e[i].n)
63      {
64          int to=e[i].to;
65          if(to==faa)continue;
66          check(to,x,root,kx+1);
67      }
68      return ;
69 }
70 int ans=0;
71 void work()
72 {
73     while(!q.empty())
74     {
75         int top=q.top().second;
76         //printf("top=%d\n",top);
77         q.pop();
78         if(vis[top]==1)continue;
79         int faa=find(top,k);
80         //printf("faa=%d\n",faa);
81         check(faa,0,faa,0);
82         ans++;
83     }
84 }
85 signed main()
86 {
87     n=read();k=read();t=read();
88     for(int i=1;i<=n-1;++i)
89     {
90         int x,y;
91         x=read();y=read();
92         add(x,y);add(y,x);
93     }
94     deep[1]=1;
95     DFS(1,0);
96     work();
97     printf("%d\n",ans);
98 }
View Code

还有要注意的一点,在找与祖先相邻为k的点时暴力查找,不看深度。。。。

猜你喜欢

转载自www.cnblogs.com/Wwb123/p/11336045.html