bzoj1487: [HNOI2009]无归岛

来源:互联网 发布:php工程师需要具备 编辑:程序博客网 时间:2024/05/10 02:45

传送门
如果原图不是仙人掌,就是一个傻逼的树形dp
可是他就是仙人掌。
考虑破环为链。
强制断开一条边。在链上跑dp,在最后状态中求出合法的最大值就ok辣。

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define N 100005#define inf 2000000000using namespace std;int n,m,x,y,tot,tim;int f[N],g[N],val[N],head[N],dfn[N],fa[N];struct edge{    int to,next;}e[N*4];inline int read(){    int x=0,f=1;    char ch=getchar();    while (ch<'0'||ch>'9'){        if (ch=='-') f=-1;        ch=getchar();    }    while (ch>='0'&&ch<='9'){        x=x*10+ch-48;        ch=getchar();    }    return x*f;}inline void ins(int x,int y){    e[++tot].to=y;    e[tot].next=head[x];    head[x]=tot;}void dp(int rt,int x){    int u0=0,u1=0,v0,v1;    for (int i=x;i!=rt;i=fa[i]){        v1=u0+f[i];        v0=u1+g[i];        u0=v0;        u1=max(v1,v0);    }    g[rt]+=u1;    u0=-inf,u1=0;    for (int i=x;i!=rt;i=fa[i]){        v1=u0+f[i];        v0=u1+g[i];        u0=v0;        u1=max(v1,v0);    }    f[rt]+=u0;}void dfs(int x){    dfn[x]=++tim;    for (int i=head[x];i;i=e[i].next)        if (!dfn[e[i].to]){            fa[e[i].to]=x;            dfs(e[i].to);        }    f[x]=val[x];    for (int i=head[x];i;i=e[i].next)        if (dfn[e[i].to]>dfn[x]&&fa[e[i].to]!=x) dp(x,e[i].to);}int main(){    n=read();    m=read();    for (int i=1;i<=m;i++){        x=read();        y=read();        ins(x,y);        ins(y,x);    }    for (int i=1;i<=n;i++) val[i]=read();    dfs(1);    printf("%d",max(f[1],g[1]));}
0 0
原创粉丝点击