zoukankan      html  css  js  c++  java
  • [Poi2011]Dynamite

    问题:

    某个点上的引线被点燃后的1单位时间内,在树上和它相邻的点的引线会被点燃。如果一个有炸 药的点的引信被点燃,那么这个点上的炸 药会爆炸。
    求引爆所有炸 药的最短时间。

    解:

    树形DP+二分答案

    设$f1[x]$表示距离x最远的未被点然的炸弹 

        $f2[x]$表示距离x最近的已经被点燃过的炸弹

    $f1[x]=max(f1[x],f1[u]) $   u是x的儿子

    $f2[x]=min(f2[x],f2[u]) $   u是x的儿子

    后序遍历 三种情况

      if(isbo[v]&&f2[v]>t) {
                f1[v]=max(0,f1[v]);             //v是未盖点 取max
            }
        if(f1[v]+f2[v]<=t) {f1[v]=-10000000;}    //能被盖住
        if(f1[v]==t) {num++;f2[v]=0; f1[v]=-10000000;}  //必须要点然
        }

    DP即可 注意判断根的情况

    code:

    #include<stdio.h> 
    #include<cstdlib> 
    #include<ctime> 
    #include<algorithm> 
    using namespace std; 
    #define maxnn 4000000 
    #define inf 100000000 
    int isbo[maxnn]; 
    int f[maxnn];
    int f1[maxnn],f2[maxnn]; 
    int n,m; 
    int t;
    int cnt[maxnn],tr; 
    int las[maxnn],nex[maxnn],en[maxnn],le[maxnn],tot; 
     inline int read()
        {
            int x=0,f=1;char ch=getchar();
            while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
            while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
            return x*f;
        }
    void add(int a,int b) 
    { 
        en[++tot]=b; 
        nex[tot]=las[a]; 
        las[a]=tot; 
    } 
    void dfs(int fa,int v)
    {
        f[v]=fa;
        for(int i=las[v];i;i=nex[i]) 
        { 
            int u=en[i]; 
            if(u!=fa) 
            {
                dfs(v,u);
            }
        }
        cnt[++tr]=v;
     } 
    int bfs() 
    {     int num=0; 
        for(int y=1;y<=tr;y++)
        {
        int v=cnt[y];
        if(isbo[v]) f1[v]=0; 
        else f1[v]=-100000000; 
        f2[v]=inf; 
        for(int i=las[v];i;i=nex[i]) 
        { 
            int u=en[i]; 
            if(u!=f[v]) 
            { 
                f1[v]=max(f1[v],f1[u]+1); 
                f2[v]=min(f2[v],f2[u]+1); 
            }     
             
        } 
        if(isbo[v]&&f2[v]>t) {
                f1[v]=max(0,f1[v]);
            }
        if(f1[v]+f2[v]<=t) {f1[v]=-10000000;}
        if(f1[v]==t) {num++;f2[v]=0; f1[v]=-10000000;} 
        }
        return num; 
    } 
    bool ch() 
    { 
        int tot=bfs(); 
        if(f1[1]>=0) tot++;
        return tot<=m; 
    } 
    int main(){ 
        n=read();m=read();
        int s; 
        int x,y,z; 
        int l=0,r=n-1;
        for(int i=1;i<=n;i++) 
        { 
            isbo[i]=read();
        } 
        for(int i=1;i<n;i++) 
        { 
            x=read();
            y=read(); 
            add(x,y); 
            add(y,x); 
        } 
        dfs(1,1);
        int mid;
        while(l<=r) 
        { 
             mid=(l+r)/2; 
            t=mid;
            if(ch()) r=mid-1; 
            else 
            l=mid+1; 
        } 
        printf("%d",(l));
    }
    刀剑映出了战士的心。而我的心,漆黑且残破
  • 相关阅读:
    基于Andoird 4.2.2的同步框架源代码学习——同步发起端
    C#MD5为密码加密
    YOUYOU深入学习Ganglia之三(gmetad的软件架构)
    js原生appendChild的bug
    Spring MVC 教程,快速入门,深入分析
    Centos 6.4 Linux 相关问题总结
    jQuery插件之-瀑布流插件
    编辑简单的 shell程序
    Qt国际化相关类
    三层架构与MVC
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11370668.html
Copyright © 2011-2022 走看看