bzoj 2525 [Poi2011]Dynamite

传送门

 

题解:

二分答案+贪心

这个树上贪心在回溯时处理,需要注意一些细节。

如果传上来的这棵子树有未炸的药,传最远药的距离。如果没有,传最近的点燃引线的距离。

在判断时,如果没有药,接着向上传引线。

如果有,但是最近的引线可以拐个弯在规定时间内炸掉最远的药,视为没有药。

否则,如果最远距离未超过规定时间,接着向上传药距离。

否则点燃这一点,向上传没有药。

注意<=与<以及0的特判。

代码:

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 using namespace std;
  9 struct pai{
 10     int first,second;
 11 };
 12 #define mmin(a,b) (a<b?a:b)
 13 struct tree{
 14     int u,v,next;
 15 }l[601000];
 16 int lian[301000],n,e,ans,m,num,jie,inf=100000000;
 17 bool pd[301000];
 18 void bian(int,int);
 19 pai dfs(int,int);
 20 int main()
 21 {
 22 //    freopen("in.txt","r",stdin);
 23     scanf("%d%d",&n,&m);
 24     for(int i=1;i<=n;i++)
 25     {
 26         int x;
 27         scanf("%d",&x);
 28         pd[i]=x;
 29     }
 30     for(int i=1;i<n;i++)
 31     {
 32         int x,y;
 33         scanf("%d%d",&x,&y);
 34         bian(x,y);
 35         bian(y,x);
 36     }
 37     int le=0,ri=n;
 38     while(le<=ri)
 39     {
 40         int mid=(le+ri)>>1;
 41         num=0;jie=mid;
 42         pai pa=dfs(1,1);
 43         if(pa.second!=0) num++;
 44         if(num<=m)
 45         {
 46             ans=mid;
 47             ri=mid-1;
 48         }
 49         else
 50             le=mid+1;
 51     }
 52     printf("%d\n",ans);
 53     return 0;
 54 }
 55 void bian(int x,int y)
 56 {
 57     e++;
 58     l[e].u=x;
 59     l[e].v=y;
 60     l[e].next=lian[x];
 61     lian[x]=e;
 62 }
 63 pai dfs(int x,int fa)
 64 {
 65     pai pa;
 66     int yuan=inf,v;
 67     int que[4]={0,0},size=0;
 68     for(int i=lian[x];i;i=l[i].next)
 69     {
 70         v=l[i].v;
 71         if(v!=fa)
 72         {
 73             pa=dfs(v,x);
 74             if(pa.second==0) yuan=mmin(yuan,pa.first);
 75             else
 76             {
 77                 size++;
 78                 if(que[1]<pa.first) que[1]=pa.first;
 79                 if(que[0]<=pa.first) swap(que[0],que[1]);
 80             }
 81         }
 82     }
 83     if(pd[x]==1&&jie==0)
 84     {
 85         num++;
 86         return (pai){0,0};
 87     }
 88     if(size==0)
 89     {
 90         if(pd[x]==0||yuan<=jie) return (pai){yuan+1,0};
 91         return (pai){1,1};
 92     }
 93     if(que[0]+yuan<=jie)
 94     {
 95         return (pai){yuan+1,0};
 96     }
 97     if(que[0]<jie) return (pai){que[0]+1,1};
 98     num++;
 99     return (pai){1,0};
100 }
View Code

 

posted @ 2017-10-31 06:20  hzoi_wangxh  阅读(161)  评论(0编辑  收藏  举报