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;
}

原文地址:https://www.cnblogs.com/Mychael/p/9004512.html