• BZOJ2286: [Sdoi2011]消耗战


    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

    HINT

     对于100%的数据,2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1


    题解Here!

    本蒟蒻的第一道虚树题。

    那个$mgeq1$是来搞笑的嘛。。。
    这个题虚树搞一搞就好了。
    至于虚树是个啥,详见这里:

    虚树学习笔记

    于是这个题就每次在叙述上跑$DP$就好。
    复杂度$O(2sum k)$,跑得飞快。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define MAXN 250010
    using namespace std;
    int n,m,c=1,d=1,e=1;
    int top_stack,stack[MAXN];
    int head_a[MAXN],head_b[MAXN],h[MAXN],deep[MAXN],size[MAXN],son[MAXN],fa[MAXN],id[MAXN],top[MAXN];
    long long val[MAXN],dp[MAXN];
    struct Tree{
    	int next,to,w;
    }a[MAXN<<1];
    struct New_Tree{
    	int next,to;
    }b[MAXN<<1];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline bool cmp(const int &p,const int &q){
    	return id[p]<id[q];
    }
    inline void add_a(int u,int v,int w){
    	a[c].to=v;a[c].w=w;a[c].next=head_a[u];head_a[u]=c++;
    	a[c].to=u;a[c].w=w;a[c].next=head_a[v];head_a[v]=c++;
    }
    inline void add_b(int x,int y){
    	b[e].to=y;b[e].next=head_b[x];head_b[x]=e++;
    }
    void dfs1(int rt){
    	son[rt]=0;size[rt]=1;
    	for(int i=head_a[rt];i;i=a[i].next){
    		int will=a[i].to;
    		if(!deep[will]){
    			deep[will]=deep[rt]+1;
    			val[will]=min(val[rt],1LL*a[i].w);
    			fa[will]=rt;
    			dfs1(will);
    			size[rt]+=size[will];
    			if(size[will]>size[son[rt]])son[rt]=will;
    		}
    	}
    }
    void dfs2(int rt,int f){
    	id[rt]=d++;top[rt]=f;
    	if(son[rt])dfs2(son[rt],f);
    	for(int i=head_a[rt];i;i=a[i].next){
    		int will=a[i].to;
    		if(will!=fa[rt]&&will!=son[rt])dfs2(will,will);
    	}
    }
    int LCA(int x,int y){
    	while(top[x]!=top[y]){
    		if(deep[top[x]]<deep[top[y]])swap(x,y);
    		x=fa[top[x]];
    	}
    	if(deep[x]>deep[y])swap(x,y);
    	return x;
    }
    void push(int x){
    	if(top_stack==1){
    		stack[++top_stack]=x;
    		return;
    	}
    	int lca=LCA(x,stack[top_stack]);
    	if(lca==stack[top_stack])return;
    	while(top_stack>1&&id[stack[top_stack-1]]>=id[lca]){
    		add_b(stack[top_stack-1],stack[top_stack]);
    		stack[top_stack--]=0;
    	}
    	if(lca!=stack[top_stack]){
    		add_b(lca,stack[top_stack]);
    		stack[top_stack]=lca;
    	}
    	stack[++top_stack]=x;
    }
    void dfs(int rt){
    	dp[rt]=0;
    	int will;
    	bool leaf=true;
    	for(int i=head_b[rt];i;i=b[i].next){
    		leaf=false;
    		will=b[i].to;
    		dfs(will);
    		dp[rt]+=dp[will];
    	}
    	if(leaf)dp[rt]=val[rt];
    	else dp[rt]=min(dp[rt],val[rt]);
    	head_b[rt]=0;
    }
    void work(){
    	int k;
    	while(m--){
    		e=1;
    		k=read();
    		for(int i=1;i<=k;i++)h[i]=read();
    		sort(h+1,h+k+1,cmp);
    		top_stack=1;
    		stack[top_stack]=1;
    		for(int i=1;i<=k;i++)push(h[i]);
    		while(top_stack){
    			add_b(stack[top_stack-1],stack[top_stack]);
    			stack[top_stack--]=0;
    		}
    		dfs(1);
    		printf("%lld
    ",dp[1]);
    	}
    }
    void init(){
    	int u,v,w;
    	n=read();
    	for(int i=1;i<n;i++){
    		u=read();v=read();w=read();
    		add_a(u,v,w);
    	}
    	m=read();
    	deep[1]=1;val[1]=(1LL<<60);
    	dfs1(1);
    	dfs2(1,1);
    }
    int main(){
    	init();
    	work();
    	return 0;
    }
    
  • 相关阅读:
    android修改debug keystore文件使之和正式keystore sha1一致
    scrollView中可以自由滚动的listview
    android gradle的全局管理
    OpenGL学习笔记(三)
    OpenGL学习笔记(二)
    OpenGL学习笔记(一)
    Java编程代码规范中值得留意的地方
    mac上编译Android的arm64位ffmpeg
    入门程序员必读的10本经典书单
    [Android文档翻译]设备兼容性
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/10583399.html
Copyright © 2020-2023  润新知