zoukankan      html  css  js  c++  java
  • BZOJ1487 [HNOI2009]无归岛 【仙人掌dp】

    题目链接

    BZOJ1487

    题解

    就是一个简单的仙人掌最大权独立集
    还是不会圆方树
    老老实实地树形Dp + 环处理

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
    using namespace std;
    const int maxn = 100005,maxm = 400005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int h[maxn],ne = 2;
    struct EDGE{int to,nxt;}ed[maxm];
    inline void build(int u,int v){
    	ed[ne] = (EDGE){v,h[u]}; h[u] = ne++;
    	ed[ne] = (EDGE){u,h[v]}; h[v] = ne++;
    }
    int n,m,f[maxn][2],val[maxn],dfn[maxn],low[maxn],fa[maxn],cnt;
    int c[maxn],ci,g[maxn][2];
    void DP(int rt,int u){
    	ci = 0;
    	for (int i = u; i != rt; i = fa[i]) c[++ci] = i;
    	//printf("%d ",rt);
    	//REP(i,ci) printf("%d ",c[i]); puts("");
    	//not choose rt
    	g[1][0] = f[c[1]][0]; g[1][1] = f[c[1]][1];
    	for (int i = 2; i <= ci; i++){
    		g[i][0] = max(g[i - 1][0],g[i - 1][1]) + f[c[i]][0];
    		g[i][1] = g[i - 1][0] + f[c[i]][1];
    	}
    	f[rt][0] += max(g[ci][0],g[ci][1]);
    	//choose rt
    	g[1][0] = f[c[1]][0]; g[1][1] = -INF;
    	for (int i = 2; i <= ci; i++){
    		g[i][0] = max(g[i - 1][0],g[i - 1][1]) + f[c[i]][0];
    		g[i][1] = g[i - 1][0] + f[c[i]][1];
    	}
    	f[rt][1] += g[ci][0];
    }
    void dfs(int u){
    	dfn[u] = low[u] = ++cnt; f[u][1] = val[u];
    	Redge(u) if ((to = ed[k].to) != fa[u]){
    		if (!dfn[to]){
    			fa[to] = u; dfs(to);
    			low[u] = min(low[u],low[to]);
    		}
    		else low[u] = min(low[u],dfn[to]);
    		if (low[to] > dfn[u]){
    			f[u][0] += max(f[to][0],f[to][1]);
    			f[u][1] += f[to][0];
    		}
    	}
    	Redge(u) if (fa[to = ed[k].to] != u && dfn[u] < dfn[to])
    		DP(u,to);
    }
    int main(){
    	n = read(); m = read();
    	while (m--) build(read(),read());
    	REP(i,n) val[i] = read();
    	int ans = 0;
    	REP(i,n) if (!dfn[i]){
    		dfs(i);
    		ans += max(f[i][0],f[i][1]);
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    hdu 5087(次长上升子序列)
    hdu 5086(递推)
    hdu 5084(矩阵操作)
    hdu 5083(模拟)
    hdu 5082(水题)
    高数准备:
    ★ phpStudy安装SSL证书实现https链接
    phpStudy环境安装SSL证书教程
    Qt中切换窗口功能的实现
    LeetCode OJ:Reverse Linked List II(反转链表II)
  • 原文地址:https://www.cnblogs.com/Mychael/p/9004512.html
Copyright © 2011-2022 走看看