EOJ3654管理孩子(贪心,二分答案)
Posted myx12345
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EOJ3654管理孩子(贪心,二分答案)相关的知识,希望对你有一定的参考价值。
题意:有一棵n个点的树,其中有k个是关键点,将树分割成若干部分,每部分至少包含一个关键点,求最大分割大小的最小值
思路:
最后特判一下f[1]的值
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<map> 8 #include<queue> 9 #include<vector> 10 #include<ctime> 11 using namespace std; 12 typedef long long ll; 13 typedef unsigned int uint; 14 typedef unsigned long long ull; 15 typedef pair<int,int> PII; 16 typedef vector<int> VI; 17 #define fi first 18 #define se second 19 #define MP make_pair 20 #define mem0(a) memset(a,0,sizeof(a)) 21 #define N 210000 22 #define M 130 23 #define MOD 1000000007 24 #define eps 1e-8 25 #define pi acos(-1) 26 #define oo 1000000000 27 28 int flag[N],f[N],a[N],n,mx; 29 vector<int>c[N]; 30 31 void dfs(int u) 32 { 33 flag[u]=1; 34 if(a[u]) 35 { 36 int t=0; 37 for(int i=0;i<=(int)c[u].size()-1;i++) 38 { 39 int v=c[u][i]; 40 if(!flag[v]) 41 { 42 dfs(v); 43 if(f[v]<0) t-=f[v]; 44 } 45 } 46 f[u]=t+1; 47 } 48 else 49 { 50 int t=0,s=oo; 51 for(int i=0;i<=(int)c[u].size()-1;i++) 52 { 53 int v=c[u][i]; 54 if(!flag[v]) 55 { 56 dfs(v); 57 if(f[v]<0) t-=f[v]; 58 else s=min(s,f[v]); 59 } 60 } 61 if(mx-s>=t+1) f[u]=s+t+1; 62 else f[u]=-t-1; 63 } 64 } 65 66 int isok(int m) 67 { 68 mem0(flag); 69 mem0(f); 70 mx=m; 71 dfs(1); 72 int flag=1; 73 if(f[1]<0) return 0; 74 for(int i=1;i<=n;i++) 75 if(abs(f[i])>m) return 0; 76 return 1; 77 } 78 79 int main() 80 { 81 int k; 82 scanf("%d%d",&n,&k); 83 for(int i=1;i<=n-1;i++) 84 { 85 int x,y; 86 scanf("%d%d",&x,&y); 87 c[x].push_back(y); 88 c[y].push_back(x); 89 } 90 for(int i=1;i<=k;i++) 91 { 92 int x; 93 scanf("%d",&x); 94 a[x]=1; 95 } 96 int l=1,r=n,last=n; 97 while(l<=r) 98 { 99 int mid=(l+r)>>1; 100 if(isok(mid)){last=mid; r=mid-1;} 101 else l=mid+1; 102 } 103 printf("%d ",last); 104 return 0; 105 }
以上是关于EOJ3654管理孩子(贪心,二分答案)的主要内容,如果未能解决你的问题,请参考以下文章