[bzoj2286] [SDOI2011]消耗战

Description

在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。

侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到1号岛屿上)。不过侦查部门还发现了这台机器只能够使用m次,所以我们只需要把每次任务完成即可。

Input

第一行一个整数n,代表岛屿数量。

接下来n-1行,每行三个整数u,v,w,代表u号岛屿和v号岛屿由一条代价为c的桥梁直接相连,保证1<=u,v<=n且1<=c<=100000。

第n+1行,一个整数m,代表敌方机器能使用的次数。

接下来m行,每行一个整数ki,代表第i次后,有ki个岛屿资源丰富,接下来k个整数h1,h2,…hk,表示资源丰富岛屿的编号。

Output

输出有m行,分别代表每次任务的最小代价。

Sample Input

10
1 5 13
1 9 6
2 1 19
2 4 8
2 3 91
5 6 8
7 5 4
7 8 31
10 7 9
3
2 10 6
4 5 7 8 3
3 9 4 6

Sample Output

12
32
22

Solution

虚树入门题。

注意如果一个点被标记了,它子树下也有被标记的点,下面的点可以删掉,然后dp。

#include<bits/stdc++.h>
using namespace std;

#ifdef ONLINE_JUDGE
#define getchar() ((p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2)?EOF:*p1++)
#endif

namespace fast_IO {
	char buf[1<<21],*p1=buf,*p2=buf;

	template <typename T> inline void read(T &x) {
		x=0;T f=1;char ch=getchar();
		for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
		for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
	}
	template <typename T,typename... Args> inline void read(T& x,Args& ...args) {
		read(x),read(args...);
	}

	char buf2[1<<21],a[80];int p,p3=-1;

	inline void flush() {fwrite(buf2,1,p3+1,stdout),p3=-1;}
	template <typename T> inline void write(T x) {
		if(p3>(1<<20)) flush();
		if(x<0) buf2[++p3]='-',x=-x;
		do {a[++p]=x%10+48;} while(x/=10);
		do {buf2[++p3]=a[p];} while(--p);
		buf2[++p3]='\n';flush();
	}
	template <typename T,typename... Args> inline void write(T x,Args ...args) {
		write(x),write(args...);
	}
}

using fast_IO :: read;
using fast_IO :: write;
using fast_IO :: flush;

#define ll long long 

const int maxn = 2.5e5+10;
const int inf = 1e9;

int mn[maxn],dfn[maxn],n,sz[maxn];
ll f[maxn];

struct Normal_Tree {
	int head[maxn],tot,dfn_cnt,f[maxn][20],dep[maxn];
	struct edge{int to,nxt,w;}e[maxn<<1];
	void add(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;}
	void ins(int u,int v,int w) {add(u,v,w),add(v,u,w);}
	void dfs(int x,int fa) {
		dfn[x]=++dfn_cnt;f[x][0]=fa;dep[x]=dep[fa]+1;sz[x]=1;
		for(int i=1;i<=17;i++) f[x][i]=f[f[x][i-1]][i-1];
		for(int i=head[x];i;i=e[i].nxt)
			if(e[i].to!=fa) mn[e[i].to]=min(mn[x],e[i].w),dfs(e[i].to,x),sz[x]+=sz[e[i].to];
	}
	int lca(int x,int y) {
		if(dep[x]<dep[y]) swap(x,y);
		for(int i=17;~i;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
		if(x==y) return x;
		for(int i=17;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
		return f[x][0];
	}
}T;

int cmp(int x,int y) {return dfn[x]<dfn[y];}

struct Virtual_Tree {
	int head[maxn],tot,sta[maxn],use[maxn],in[maxn],top,used,a[maxn];
	struct edge{int to,nxt;}e[maxn<<1];
	void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
	void ins(int u,int v) {add(u,v),add(v,u);}
	void dfs(int x,int fa) {
		int bo=1;
		for(int i=head[x];i;i=e[i].nxt)
			if(e[i].to!=fa) dfs(e[i].to,x),f[x]+=min((ll)mn[e[i].to],f[e[i].to]),bo=0;
		if(bo) f[x]=mn[x];
		//printf("Dfs:%d %d\n",x,f[x]);
	}
	void solve() {
		int k;read(k);top=used=0;
		for(int i=1;i<=k;i++) read(a[i]);
		sort(a+1,a+k+1,cmp);int p=0;
		for(int i=1;i<=k;i++)
			if(dfn[a[i]]>dfn[in[p]]+sz[in[p]]-1) in[++p]=a[i];
		k=p;
		sta[++top]=1;use[++used]=1;
		for(int i=1;i<=k;i++) {
			if(in[i]==1) continue;
			int t=T.lca(in[i],sta[top]),pre=-1;
			while(dfn[sta[top]]>dfn[t]&&dfn[sta[top]]<dfn[t]+sz[t]) {
				if(pre!=-1) ins(sta[top],pre);
				pre=sta[top];use[++used]=sta[top];top--;
			}
			if(pre!=-1) ins(t,pre);
			if(sta[top]!=t) sta[++top]=t;
			sta[++top]=in[i];
		}
		int pre=-1;
		while(top) {
			if(pre!=-1) ins(sta[top],pre);
			pre=sta[top],use[++used]=sta[top];top--;
		}
		dfs(1,0),write(f[1]);
		for(int i=1;i<=used;i++) head[use[i]]=0,f[use[i]]=0;
		tot=0;
	}
}VT;

int main() {
	read(n);
	for(int i=1,x,y,z;i<n;i++) read(x,y,z),T.ins(x,y,z);
	for(int i=1;i<=n;i++) mn[i]=inf,f[i]=0;T.dfs(1,0);mn[1]=0;
	int t;read(t);
	while(t--) VT.solve();
	flush();
	return 0;
}
posted @ 2019-01-03 19:49  Hyscere  阅读(163)  评论(0编辑  收藏  举报