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]消耗战
  • 相关阅读:
    CodeForces Gym 100500A A. Poetry Challenge DFS
    CDOJ 486 Good Morning 傻逼题
    CDOJ 483 Data Structure Problem DFS
    CDOJ 482 Charitable Exchange bfs
    CDOJ 481 Apparent Magnitude 水题
    Codeforces Gym 100637G G. #TheDress 暴力
    Gym 100637F F. The Pool for Lucky Ones 暴力
    Codeforces Gym 100637B B. Lunch 找规律
    Codeforces Gym 100637A A. Nano alarm-clocks 前缀和
    TC SRM 663 div2 B AABB 逆推
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14401779.html
Copyright © 2011-2022 走看看