●洛谷P2495 [SDOI2011]消耗战

题链:

https://www.luogu.org/problemnew/show/P2495
题解:

虚树入门,树形dp
推荐博客:http://blog.csdn.net/lych_cys/article/details/50814948


代码:

 

#include<bits/stdc++.h>
#define MAXN 250005
#define INFll 0x3f3f3f3f3f3f3f3fll
using namespace std;
int N,Q,M;
bool mark[MAXN];
long long val[MAXN];
int mincut[MAXN],dfn[MAXN],deep[MAXN],fa[MAXN][19];
struct Edge{
	int ent;
	int to[MAXN*2],val[MAXN*2],nxt[MAXN*2],head[MAXN];
	Edge(){ent=2;}
	void Adde(int u,int v,int w){
		to[ent]=v; val[ent]=w;
		nxt[ent]=head[u]; head[u]=ent++;
	}
}E1,E2;
bool cmp(int a,int b){return dfn[a]<dfn[b];}
void read(int &x){
	static int sign; static char ch;
	sign=1; x=0; ch=getchar();
	for(;ch<'0'||'9'<ch;ch=getchar()) if(ch=='-') sign=-1;
	for(;'0'<=ch&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	if(sign==-1) x=-x;
}
void dfs(int u,int dep){
	static int dnt;
	dfn[u]=++dnt; deep[u]=dep;
	for(int k=1;k<19;k++)
		fa[u][k]=fa[fa[u][k-1]][k-1];
	for(int e=E1.head[u];e;e=E1.nxt[e]){
		int v=E1.to[e]; if(v==fa[u][0]) continue;
		fa[v][0]=u; val[v]=min(val[u],1ll*E1.val[e]);
		dfs(v,dep+1);
	}
}
int LCA(int u,int v){
	if(deep[u]>deep[v]) swap(u,v);
	for(int k=18;k>=0;k--) if(deep[fa[v][k]]>=deep[u]) v=fa[v][k];
	if(u==v) return u;
	for(int k=18;k>=0;k--) if(fa[u][k]!=fa[v][k]) u=fa[u][k],v=fa[v][k];
	return fa[u][0];
}
long long dp(int u){
	if(!E2.head[u]) return val[u];
	long long tmp=0;
	for(int e=E2.head[u];e;e=E2.nxt[e]){
		int v=E2.to[e]; tmp+=dp(v);
	}
	E2.head[u]=0; 
	if(mark[u]) return val[u];
	return min(tmp,val[u]);
}
void solve(){
	static int a[MAXN*2],stk[MAXN*2],top,lca;
	read(M); E2.ent=2; top=0;
	for(int i=1;i<=M;i++) read(a[i]),mark[a[i]]=1;
	//虚树的构建------------------------------------
	sort(a+1,a+M+1,cmp); stk[++top]=1;
	for(int i=1;i<=M;i++){
		lca=LCA(stk[top],a[i]);
		if(lca!=stk[top]) while(1){
			if(dfn[stk[top-1]]<=dfn[lca]){
				E2.Adde(lca,stk[top],0),top--;
				if(stk[top]!=lca) stk[++top]=lca;
				break;
			}
			E2.Adde(stk[top-1],stk[top],0),top--;
		}
		if(stk[top]!=a[i]) stk[++top]=a[i];
	}
	while(top>1) E2.Adde(stk[top-1],stk[top],0),top--;
	//-----------------------------------------------
	printf("%lld\n",dp(1));
	for(int i=1;i<=M;i++) mark[a[i]]=0;
}
int main(){
	read(N);
	for(int i=1,a,b,c;i<N;i++){
		read(a),read(b),read(c);
		E1.Adde(a,b,c); E1.Adde(b,a,c);
	}
	val[1]=INFll; dfs(1,1); read(Q);
	while(Q--) solve();
	return 0;
}

 

  

 

posted @ 2018-03-12 21:31  *ZJ  阅读(176)  评论(0编辑  收藏  举报