[SDOI2011] 消耗战
Posted fengxunling
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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;
}
}
以上是关于[SDOI2011] 消耗战的主要内容,如果未能解决你的问题,请参考以下文章