zoukankan      html  css  js  c++  java
  • 【模拟8.11】将军令(贪心&&树形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);
    72        return 0;
    73     }
    74     DFS(1,0);
    75     printf("%lld
    ",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
    ",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
    ",top);
    77         q.pop();
    78         if(vis[top]==1)continue;
    79         int faa=find(top,k);
    80         //printf("faa=%d
    ",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
    ",ans);
    98 }
    View Code

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

  • 相关阅读:
    Linux shell 学习总结
    linux shell 比较总结
    NSURL基本操作 HA
    Mac node.js install HA
    nodejs学习资料收集 HA
    xcode技巧 HA
    google web app/enxtions 学习资料收集 HA
    Failed to upload *.app on Device 可能的解决方法 HA
    iphone开发常见问题小集2 HA
    cocos2d收集 HA
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11336045.html
Copyright © 2011-2022 走看看