• 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
    ",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
  • 相关阅读:
    读《大道至简》第6章有感
    Java作业05(动手动脑)
    读《大道至简》第五章有感
    java作业04(动手动脑)
    域名与主机名
    STL 迭代器学习
    数组与链表增删改查效率比较
    智能指针多线程安全问题
    快速乘 学习
    关于TCP三个冗余ACK启动快速重传
  • 原文地址:https://www.cnblogs.com/hzoi-wangxh/p/7759739.html
Copyright © 2020-2023  润新知