将军令(贪心&&树形DP)
Posted wwb123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将军令(贪心&&树形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 nodeint 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
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 nodeint 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
还有要注意的一点,在找与祖先相邻为k的点时暴力查找,不看深度。。。。
以上是关于将军令(贪心&&树形DP)的主要内容,如果未能解决你的问题,请参考以下文章