• BZOJ 2286 [Sdoi2011]消耗战 ——虚树


    虚树第一题。

    大概就是建一颗只与询问有关的更小的新树,然后在虚树上DP

    #include <map>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define ll long long
    #define inf 1e17
    #define maxn 500005
     
    int n,m,k,a[maxn];
    int h[maxn],to[maxn],ne[maxn],w[maxn],en=0;
    int dep[maxn],st[maxn][21],_log[maxn],in[maxn],out[maxn],tot,ord[maxn];
    ll mn[maxn];int sta[maxn],top=0,last[maxn],idx=0;
     
    void add(int a,int b,int c)
    {to[en]=b;ne[en]=h[a];w[en]=c;h[a]=en++;}
     
    void dfs(int o,int fa)
    {
        in[o]=++tot;ord[tot]=o;
        for (int i=h[o];i>=0;i=ne[i])
        if (to[i]!=fa){
            dep[to[i]]=dep[o]+1;
            mn[to[i]]=min(mn[o],(ll)w[i]);
            dfs(to[i],o);
            ord[++tot]=o;
        }
        out[o]=tot;
    }
     
    void initst()
    {
        F(i,2,maxn-1) _log[i]=_log[i>>1]+1;
        F(i,1,20) F(j,1,tot-(1<<i)+1)
        {
            if (dep[st[j][i-1]]<dep[st[j+(1<<i-1)][i-1]]) st[j][i]=st[j][i-1];
                else st[j][i]=st[j+(1<<i-1)][i-1];
        }
    }
     
    int lca(int l,int r)
    {
        if (l==r) return l;
        l=in[l],r=in[r];
        if (l>r) swap(l,r);
        int tmp=_log[r-l+1];// printf("tmp is %d
    ",tmp);
        if (dep[st[l][tmp]]<dep[st[r-(1<<tmp)+1][tmp]]) return st[l][tmp];
        else return st[r-(1<<tmp)+1][tmp];
    }
     
    bool cmp(int a,int b)
    {return in[a]<in[b];}
     
    int hd[maxn],tl[maxn],nxt[maxn],ed,se[maxn];
     
    void add_edge(int a,int b)
    {
        if (last[a]!=idx) last[a]=idx,hd[a]=-1;
        tl[ed]=b;
        nxt[ed]=hd[a];
        hd[a]=ed++;
    }
     
    ll dfs2(int o,int fa)
    {
        ll ret=0;
        for (int i=hd[o];i>=0;i=nxt[i])
            if (tl[i]!=fa)
                ret+=dfs2(tl[i],o);
        if(se[o]==idx) return mn[o];
        return min(ret,(ll)mn[o]);
    }
     
    int main()
    {
        memset(h,-1,sizeof h);
        scanf("%d",&n); mn[1]=inf;
        F(i,1,n-1)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);add(b,a,c);
        }
        dfs(1,0);
        F(i,1,tot)st[i][0]=ord[i];initst();
        scanf("%d",&m);
        while (m--)
        {
            ed=0; idx++;
            scanf("%d",&k);
            F(i,1,k) scanf("%d",&a[i]),se[a[i]]=idx;
            sort(a+1,a+k+1,cmp);
            sta[top=1]=1;
            F(i,1,k)
            {
                int l=in[sta[top]],r=in[a[i]],x=lca(sta[top],a[i]);
                while (dep[sta[top]]>dep[x])
                {
                    int tmp;
                    if (dep[x]>dep[sta[top-1]]) tmp=x;
                    else tmp=sta[top-1];
                    add_edge(sta[top],tmp);
                    add_edge(tmp,sta[top]);
                    top--;
                }
                if (x!=sta[top]) sta[++top]=x;
                sta[++top]=a[i];
            }
            while (top>1) add_edge(sta[top],sta[top-1]),add_edge(sta[top-1],sta[top]),top--;
            printf("%lld
    ",dfs2(1,0));
        }
    }
    

      

  • 相关阅读:
    Minikube体验
    基于Vue、Bootstrap的Tab形式的进度展示
    Python 网络请求模块 urllib 、requests
    SRE学习笔记:分布式共识系统、Paxos协议
    ReactNative: 使用对话框组件AlertIOS组件
    ReactNative: 使用AsyncStorage异步存储类
    ReactNative: 使用网页组件WebView组件
    ReactNative: 使用标签栏组件TabBarIOS组件
    ReactNative: 使用像素密度类PixelRatio进行适配
    ReactNative: 使用尺寸类Dimensions获取屏幕尺寸
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6669946.html
Copyright © 2020-2023  润新知