zoukankan      html  css  js  c++  java
  • [ZJOI2008] 骑士

    [ZJOI2008] 骑士

    BZOJ
    luogu
    我们发现关系图由恰好n个点,n条边构成,
    这告诉我们关系图是一些基环树,
    我们可以找出这个环,对环上每个点的子树dp一遍
    再把这个环dp一遍求出答案
    树dp:设(f_i)表示选择i的子树最大价值和
    (g_i)表示不选i的子树最大价值和

    [f_u+=g_v$$$$g_u+=max(f_v,g_v) ]

    环dp:相同的状态和转移,讨论是否选1做两遍dp
    博猪抠环的方法好像复杂了,不过过了就懒得管了...
    注意图不一定连通和有重边

    #define ll long long
    #include<bits/stdc++.h>
    using namespace std;
    const int _=1e6+5;
    int re(){
    	int x=0,w=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*w;
    }
    int n,cnt,tot,top,sz,ts;
    int h[_],cir[_],st[_],fa[_],dfn[_],low[_],tmp[_];
    ll Ans,ans,g[_],f[_],F[_],G[_];
    bool vis[_];
    struct edge{int to,next;}e[_<<1];
    void link(int u,int v){
    	e[++cnt]=(edge){v,h[u]};h[u]=cnt;
    	e[++cnt]=(edge){u,h[v]};h[v]=cnt;
    }
    void tarjan(int u){
    	dfn[u]=low[u]=++ts;st[++top]=u;
    	for(int i=h[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(!dfn[v]){
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    			if(low[v]>=dfn[u]){
    				int x;sz=0;
    				do{x=st[top--];tmp[++sz]=x;}while(x^v);tmp[++sz]=u;
    				if(sz>tot){tot=sz;for(int j=1;j<=sz;j++)cir[j]=tmp[j];}
    			}
    		}
    		else low[u]=min(low[u],dfn[v]);
    	}
    }
    void dfs(int u){
    	for(int i=h[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(vis[v]||v==fa[u]||fa[v]==u)continue;//重边
    		fa[v]=u;dfs(v);f[u]+=g[v];g[u]+=max(f[v],g[v]);
    	}
    }
    int main(){
    	n=re();
    	for(int i=1;i<=n;i++){
    		f[i]=re();link(i,re());
    	}
    	for(int i=1;i<=n;i++){
    		if(dfn[i])continue;
    		top=0;tot=0;tarjan(i);
    		for(int j=1;j<=tot;j++)vis[cir[j]]=1;
    		for(int j=1;j<=tot;j++){
    			dfs(cir[j]);F[j]=f[cir[j]];G[j]=g[cir[j]];
    		}
    		G[2]+=F[1];F[3]+=G[2];G[3]+=G[2];//选择1
    		for(int j=4;j<=tot;j++){
    			F[j]+=G[j-1];
    			G[j]+=max(F[j-1],G[j-1]);
    		}
    		ans=G[tot];
    		for(int j=1;j<=tot;j++){
    			F[j]=f[cir[j]];G[j]=g[cir[j]];
    		}
    		F[2]+=G[1];G[2]+=G[1];//不选择1
    		for(int j=3;j<=tot;j++){
    			F[j]+=G[j-1];
    			G[j]+=max(F[j-1],G[j-1]);
    		}
    		ans=max(ans,max(F[tot],G[tot]));
    		Ans+=ans;
    	}
    	printf("%lld
    ",Ans);
    	return 0;
    }
    
  • 相关阅读:
    Spring配置事务中的 transactionAttributes 各属性含义及XML配置
    91. ExtJS获取父子、兄弟容器元素方法
    90.商城登录页面Extjs
    89. Ext.Button 按钮
    88. [ExtJS2.1教程-5]ToolBar(工具栏)
    87.Ext_菜单组件_Ext.menu.Menu
    86. Ext文本输入框:Ext.form.TextField属性汇总
    85.Ext.Window
    C 一个字符串有三段,第一段原样输出,第二段为要输出字符串的长度,第三段为依据第二段长度补齐第一段
    Spring in action(Spring实战) 第四版中文翻译
  • 原文地址:https://www.cnblogs.com/sdzwyq/p/9863145.html
Copyright © 2011-2022 走看看