zoukankan      html  css  js  c++  java
  • bzoj 2286: [Sdoi2011]消耗战

    题目链接

    bzoj 2286: [Sdoi2011]消耗战

    题解

    抽离虚树dp
    对于虚树我们可以O(m)构造
    dfs序排序后,易证相邻两点lca为所有出现到的lca
    每次维护一个深度递增的栈,用其来维护一个节点的虚树,当其被pop出栈时他的虚数也构造完了
    那么栈中序列即为链的父子关系
    每次若将要插入一点与栈顶点的lca,位于栈顶上个点的虚树树中,且不为栈顶点的后代<若是的话直接压入栈中,继续跟新该链>,那么弹出栈顶点后直接压入栈中,连边,否则pop到是为止,此时开始新链更新
    pop时连边建立父子关系就好了
    然后就是普通的树形dp
    ps:我一定要出一道虚树 ~~毒瘤~~ 码农题

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring> 
    #define LL long long 
    inline int read() {
        int x = 0,f =  1;
        char c = getchar();
        while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();} 
        while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); 
        return x * f;
    } 
    const int maxn = 2000007;  
    struct node {
        int w,v,next;
    } edge[maxn << 1],e[maxn << 1]; 
    int num = 1,head[maxn],dfn[maxn] ; 
    inline void add_edge(int u,int v,int w) { 
         edge[++ num].v = v;edge[num].next = head[u];head[u] = num; edge[num].w = w;} 
    int h[maxn]; 
    int num1 = 0; 
    inline void add(int u,int v) { 
        if(u == v) return ; 
        e[++ num1].v = v;e[num1].next = h[u];h[u] = num1; 
    } 
    int n,m,id = 0,dad[maxn][20],deep[maxn];LL mn[maxn];    
    void dfs(int x) {
        dfn[x] = ++id; 
        deep[x] = deep[dad[x][0]] + 1;
        for(int i = 0;dad[x][i];++ i) dad[x][i + 1] = dad[dad[x][i]][i]; 
        for(int i = head[x];i;i = edge[i].next) {
            int v = edge[i].v;
            if(v == dad[x][0]) continue; 
            dad[v][0] = x; 
            mn[v] = std::min(mn[x],(LL)edge[i].w); 
            dfs(v); 
        } 
    } 
    int lca(int x,int y) { 
        if(deep[x] > deep[y]) std::swap(x,y) ; 
        for(int i = 18;i >= 0;-- i) if(deep[dad[y][i]] >= deep[x]) y = dad[y][i];
            if(x == y) return x; 
        for(int i = 18;i >= 0;-- i) 
            if(dad[x][i] != dad[y][i]) x = dad[x][i],y = dad[y][i]; 
        return dad[x][0]; 
    } 
    int tt[maxn],stack[maxn];  
    inline bool cmp(int x,int y) {  return dfn[x] < dfn[y]; } 
    LL dp[maxn]; 
    void Dp(int x) {
        dp[x] = (LL)mn[x]; 
        LL tmp = 0; 
        for(int i = h[x];i;i = e[i].next) { 
            Dp(e[i].v);
            tmp += dp[e[i].v]; 
        } 
        h[x] = 0;//顺便清空
        if(tmp == 0) dp[x] = (LL)mn[x]; 
        else dp[x] = std::min(dp[x],tmp);//要么割自己,要么割子树 
    } 
    void solve(int k = 0,int top = 0,int tot = 0) {
        k = read(); 
        for(int i = 1;i <= k;++ i) tt[i] = read(); 
        std::sort(tt + 1,tt + k + 1,cmp); 
        stack[++ tot] = tt[1]; 
        for(int i = 2;i <= k;++ i) 
            if(lca(tt[tot],tt[i]) != tt[tot]) tt[++ tot] = tt[i]; 
        //根据题意,切掉子树的根后子树就不用管了 
        stack[++ top] = 1;  
        for(int i = 1;i <= tot;++ i) {  
            int now = tt[i],f = lca(now,stack[top]);   
            while("tle") { 
                if(deep[stack[top - 1]] <= deep[f]) {  
                    add(f,stack[top --]);  
                        if(stack[top] != f)stack[++ top] = f; 
                    break;   
                }  
                add(stack[top - 1],stack[top]) ;top --;  
            } 
            if(stack[top] != now)stack[++ top] = now;  
        }  
        while(-- top) add(stack[top],stack[top + 1]);  
        Dp(1);  
        printf("%lld
    ",dp[1]);      
    } 
    int main() { 
        n = read();  
        for(int u,v,w,i = 1;i < n;++ i) { 
            u = read();v = read();w = read(); 
            add_edge(u,v,w); add_edge(v,u,w); 
        } 
        mn[1] = 10000000000000007LL; 
        dfs(1);
        m = read(); 
        for(int i = 1;i <= m;++ i) { 
            solve();
        } 
        return 0;   
    } 
    
  • 相关阅读:
    Java程序:从命令行接收多个数字,求和并输出结果
    大道至简读后感
    大道至简第一章读后感Java伪代码
    Creating a SharePoint BCS .NET Connectivity Assembly to Crawl RSS Data in Visual Studio 2010
    声明式验证超时问题
    Error message when you try to modify or to delete an alternate access mapping in Windows SharePoint Services 3.0: "An update conflict has occurred, and you must re-try this action"
    Upgrading or Redeploying SharePoint 2010 Workflows
    Upgrade custom workflow in SharePoint
    SharePoint 2013中Office Web Apps的一次排错
    How to upgrade workflow assembly in MOSS 2007
  • 原文地址:https://www.cnblogs.com/sssy/p/9128169.html
Copyright © 2011-2022 走看看