BZOJ1487 [HNOI2009]无归岛 仙人掌dp
Posted Mychael
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1487 [HNOI2009]无归岛 仙人掌dp相关的知识,希望对你有一定的参考价值。
题目链接
题解
就是一个简单的仙人掌最大权独立集
还是不会圆方树
老老实实地树形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\n",ans);
return 0;
}
以上是关于BZOJ1487 [HNOI2009]无归岛 仙人掌dp的主要内容,如果未能解决你的问题,请参考以下文章