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\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Mychael/p/9004512.html