zoukankan      html  css  js  c++  java
  • ●洛谷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
    ",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;
    }
    

      

  • 相关阅读:
    C#中get和set的写法
    FineUI中Newtonsoft.Json版本报错解决办法
    ExtAspNet和FineUI未将对象引用设置到对象的实例
    【转载】写runat="server"有什么用
    (object sender,EventArgs e)是什么?
    【转载】onclick与onCommand的区别
    简单总结------redis
    将list等分成n份
    将List 分成n个长度由调用者指定的子List
    CountDownLatch 我的应用场景
  • 原文地址:https://www.cnblogs.com/zj75211/p/8552094.html
Copyright © 2011-2022 走看看