• [SDOI2011] 消耗战


    题目链接:戳我

    虚树(这是模板题????)
    反正是用这个学了一下虚树。其实虚树也不是什么高端玩意儿就是保留了树上有效信息剔除了没有用的信息,一般用来辅助解决树上的动态规划问题。
    虚树的讲解详情请看这个

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MAXN 300010
    using namespace std;
    int n,m,t,cnt;
    int head[MAXN<<1],fa[MAXN],dep[MAXN],dfn[MAXN],low[MAXN],done[MAXN];
    int id[MAXN],siz[MAXN],top[MAXN],son[MAXN],p[MAXN],S[MAXN];
    long long minn[MAXN];
    struct Edge{int nxt,to;long long dis;}edge[MAXN<<1];
    inline void add(int from,int to,int dis)
        {edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t;}
    inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
    inline void dfs1(int x,int f)
    {
        fa[x]=f;dep[x]=dep[f]+1;siz[x]=1;
        int maxx=-1;
        for(int i=head[x];i;i=edge[i].nxt)  
        {
            int v=edge[i].to;
            if(v==f) continue;
            minn[v]=min(minn[x],edge[i].dis);
            dfs1(v,x);
            siz[x]+=siz[v];    
            if(siz[v]>maxx) maxx=siz[v],son[x]=v;
        }
    }
    inline void dfs2(int x,int topf)
    {
        dfn[x]=++cnt;
        top[x]=topf;
        if(son[x]) dfs2(son[x],topf);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==fa[x]||v==son[x]) continue;
            dfs2(v,v);
        }
        low[x]=cnt;
    }
    inline int lca(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            x=fa[top[x]];
        }
        if(dep[x]<dep[y]) return x;
        else return y;
    }
    inline long long solve(int x)
    {
        if(done[x]) return minn[x];
        long long cur_ans=0;
        for(int i=head[x];i;i=edge[i].nxt)
            cur_ans+=solve(edge[i].to);
        return min(cur_ans,minn[x]);
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        freopen("ce.out","w",stdout);
        #endif
        scanf("%d",&n);
        memset(minn,0x3f,sizeof(minn));
        for(int i=1;i<n;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w),add(v,u,w);
        }
        dfs1(1,1);dfs2(1,1);
        scanf("%d",&m);        
        memset(head,0,sizeof(head));
        for(int i=1;i<=m;i++)
        {
            int k;
            t=0;
            scanf("%d",&k);
            for(int j=1;j<=k;j++)
            {
                scanf("%d",&p[j]);
                done[p[j]]=1;
            }
            sort(&p[1],&p[1+k],cmp);
            for(int j=k;j>1;j--)
                p[++k]=lca(p[j],p[j-1]);
            p[++k]=1;
            sort(&p[1],&p[1+k],cmp);
            k=unique(&p[1],&p[1+k])-p-1;
            for(int j=1,top=0;j<=k;j++)
            {
                while(top&&low[S[top]]<dfn[p[j]]) --top;
                add(S[top],p[j],0);
                S[++top]=p[j];
            }
            printf("%lld
    ",solve(1));
            //memset(done,0,sizeof(done));
            //memset(head,0,sizeof(head));
            for(int i=1;i<=k;++i)
                done[p[i]]=0,head[p[i]]=0;
        }
    }
    
  • 相关阅读:
    xprintf
    Socket调试助手
    ESP8266开发
    WPS for Linux 界面改为中文
    uBlock Origin 广告屏蔽
    Ubuntu删除多余旧内核
    FFmpeg命令
    Mysql-connector-java驱动版本问题
    crontab任务重复执行?不执行?不按照配置执行?大概率是配置出错了!!!
    Binding(四):数据校验
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10327928.html
Copyright © 2020-2023  润新知