zoukankan      html  css  js  c++  java
  • LG P2495 [SDOI2011]消耗战

    Description

    在一场战争中,战场由 $n$ 个岛屿和 $n-1$ 个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为 $1$ 的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他 $k$ 个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。

    侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到 $1$ 号岛屿上)。不过侦查部门还发现了这台机器只能够使用 $m$ 次,所以我们只需要把每次任务完成即可。

    Solution

    每次的询问只与某些关键点有关,建出这些关键点的虚树

    在虚树上DP即可

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n,head[250005],head2[250005],tot,tot2,m,dep[250005],fa[250005][19],lg[250005]={-1},cnt,pos[250005],sta[250005],top,dfn[250005];
    long long minn[250005];
    bool vst[250005];
    struct Edge{
        int to,nxt;
        long long w;
    }edge[500005],edge2[500005];
    inline int read(){
        int w=0,f=1;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return w*f;
    }
    void dfs1(int k,int f){
        dep[k]=dep[f]+1,fa[k][0]=f,dfn[k]=++cnt;
        for(int i=head[k];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(v!=f)minn[v]=min(minn[k],edge[i].w),dfs1(v,k);
        }
    }
    int LCA(int x,int y){
        if(dep[x]<dep[y])swap(x,y);
        while(dep[x]>dep[y])x=fa[x][lg[dep[x]-dep[y]]];
        if(x==y)return x;
        for(int i=lg[dep[x]];~i;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
    inline void addedge(int x,int y){edge2[++tot2]=(Edge){y,head2[x]},head2[x]=tot2;}
    void build(int K){
        sta[top=1]=pos[1],tot2=0;
        for(int i=2;i<=K;i++){
            int lca=LCA(pos[i],sta[top]);
            while(true)
                if(dep[lca]>=dep[sta[top-1]]){
                    if(lca!=sta[top]){
                        addedge(lca,sta[top]);
                        if(lca!=sta[top-1])sta[top]=lca;
                        else --top;
                    }
                    break;
                }
                else addedge(sta[top-1],sta[top]),--top;
            sta[++top]=pos[i];
        }
        while(--top)addedge(sta[top],sta[top+1]);
    }
    long long dfs2(int k){
        long long ret=minn[k],s=0;
        for(int i=head2[k];i;i=edge2[i].nxt)s+=dfs2(edge2[i].to);
        if(!vst[k])ret=min(ret,s);
        vst[k]=false,head2[k]=0;
        return ret;
    }
    int main(){
        memset(minn,127,sizeof(minn));
        for(int i=1;i<=250000;i++)lg[i]=lg[i>>1]+1;
        n=read();
        for(int i=1;i<n;i++){
            int u=read(),v=read(),w=read();
            edge[++tot]=(Edge){v,head[u],w},head[u]=tot,edge[++tot]=(Edge){u,head[v],w},head[v]=tot;
        }
        dfs1(1,0);
        for(int i=1;i<=18;i++)for(int k=1;k<=n;k++)fa[k][i]=fa[fa[k][i-1]][i-1];
        m=read();
        for(;m;m--){
            int K=read();
            for(int i=1;i<=K;i++)pos[i]=read(),vst[pos[i]]=true;
            sort(pos+1,pos+K+1,cmp),build(K),printf("%lld
    ",dfs2(sta[1]));
        }
        return 0;
    }
    [SDOI2011]消耗战
  • 相关阅读:
    php RSA加密传输代码示例
    数据库执行语句时,严重注意类型转换的问题
    数据库sql的in操作,解决in的过多
    php利用自定义key,对数据加解密的方法
    修改目录下所有文件的某段内容
    ajax返回json时,js获取类型,是字符串类型
    浅析单点登录,以及不同二级域名下的SSO实现
    samba服务,连接远程开发机
    『转』统计一个日志文件里,单词出现频率的shell脚本
    python的装饰器
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14401779.html
Copyright © 2011-2022 走看看