【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\n",last);    
104     return 0;         
105 }

猜你喜欢

转载自www.cnblogs.com/myx12345/p/10097092.html