码迷,mamicode.com
首页 > 其他好文 > 详细

[SDOI2011] 消耗战

时间:2019-01-28 01:00:40      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:有用   html   pre   stream   代码   while   sdoi   return   是什么   

题目链接:戳我

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

代码如下:

#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\n",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;
    }
}

[SDOI2011] 消耗战

标签:有用   html   pre   stream   代码   while   sdoi   return   是什么   

原文地址:https://www.cnblogs.com/fengxunling/p/10327928.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!