题意:给定一棵n个点带点权的树,要求从中选出一个点集,使得这些点两两之间距离都大于K,求最大点权和
n,K<=2e2,1<=a[i]<=1e5
思路:树形DP显然可做,极限是n方,然而贪心也是,还比dp好写
可以用寒假camp里cls差不多的想法
从深度大的向上贪心,暴力维护对答案的贡献,即如果贡献大于0就取,并将距当前点距离<=K的贡献减去当前点
评论区甚至有红名大佬做到了线性复杂度
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef pair<int,int> PII; 7 typedef pair<ll,ll> Pll; 8 typedef vector<int> VI; 9 typedef vector<PII> VII; 10 //typedef pair<ll,ll>P; 11 #define N 300010 12 #define M 2000010 13 #define fi first 14 #define se second 15 #define MP make_pair 16 #define pb push_back 17 #define pi acos(-1) 18 #define mem(a,b) memset(a,b,sizeof(a)) 19 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 20 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 21 #define lowbit(x) x&(-x) 22 #define Rand (rand()*(1<<16)+rand()) 23 #define id(x) ((x)<=B?(x):m-n/(x)+1) 24 #define ls p<<1 25 #define rs p<<1|1 26 27 const ll MOD=1e9+7,inv2=(MOD+1)/2; 28 double eps=1e-6; 29 int INF=1e9; 30 int dx[4]={-1,1,0,0}; 31 int dy[4]={0,0,-1,1}; 32 33 int head[N],nxt[N],vet[N],a[N],b[N],d[N],dis[N],q[N],tot,n,K; 34 35 int read() 36 { 37 int v=0,f=1; 38 char c=getchar(); 39 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 40 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 41 return v*f; 42 } 43 44 void add(int a,int b) 45 { 46 nxt[++tot]=head[a]; 47 vet[tot]=b; 48 head[a]=tot; 49 } 50 51 void dfs(int u,int fa) 52 { 53 int e=head[u]; 54 while(e) 55 { 56 int v=vet[e]; 57 if(v!=fa) 58 { 59 d[v]=d[u]+1; 60 dfs(v,u); 61 } 62 e=nxt[e]; 63 } 64 } 65 66 bool cmp(int a,int b) 67 { 68 return d[a]>d[b]; 69 } 70 71 int calc(int st) 72 { 73 rep(i,1,n) dis[i]=-1; 74 dis[st]=0; 75 int t=0,w=1; 76 q[1]=st; 77 int res=a[st]; 78 while(t<w) 79 { 80 t++; 81 int u=q[t]; 82 a[u]-=res; 83 if(dis[u]==K) continue; 84 int e=head[u]; 85 while(e) 86 { 87 int v=vet[e]; 88 if(dis[v]==-1) 89 { 90 w++; q[w]=v; dis[v]=dis[u]+1; 91 } 92 e=nxt[e]; 93 } 94 95 } 96 return res; 97 } 98 99 int main() 100 { 101 n=read(),K=read(); 102 rep(i,1,n) a[i]=read(); 103 rep(i,1,n) head[i]=0; 104 tot=0; 105 rep(i,1,n-1) 106 { 107 int x=read(),y=read(); 108 add(x,y); 109 add(y,x); 110 } 111 dfs(1,0); 112 rep(i,1,n) b[i]=i; 113 sort(b+1,b+n+1,cmp); 114 int ans=0; 115 rep(i,1,n) 116 if(a[b[i]]>0) ans+=calc(b[i]); 117 printf("%d ",ans); 118 return 0; 119 }