zoukankan      html  css  js  c++  java
  • 【BZOJ1487】无归岛(HNOI2009)-圆方树+DP

    测试地址:无归岛
    做法:本题需要用到圆方树+DP。
    很显然题目中所给的图是一个仙人掌,那么这道题要求的就是仙人掌上的最大点权和独立集。
    于是我们把仙人掌上的问题转化成圆方树上的问题。圆点上的DP很好处理,像树形DP一样处理即可,主要是方点上的DP,由于方点所在的环和它上面的圆点有两个相邻的点,所以要进行特殊判断,也就是对于一般的情况而言,dp(i,0/1)表示点i选或不选的最大点权和,而对于一个环,我们要令dp(i,0/1)表示它与上面的圆点相邻的点选或不选的最大点权和。为了方便,我们令dp(i,0)为不选某点的最大点权和,dp(i,1)可选可不选某点的最大点权和,这就很好做DP了,时间复杂度为O(n),可以通过此题。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int N=100010;
    const int M=N<<2;
    typedef long long ll;
    int n,m,first[N]={0},firsted[N<<1]={0},tot=0,totpbc;
    int low[N],dfn[N],tim=0,st[N],top=0;
    int fa[N],fae[N],cir[N];
    ll val[N],dp[N<<1][2]={0},cirdp[N][2];
    bool vis[N],inst[N];
    struct edge
    {
        int v,next,id;
    }e[M],ed[M];
    
    void insert(int a,int b,int id)
    {
        e[++tot].v=b;
        e[tot].next=first[a];
        e[tot].id=id;
        first[a]=tot;
    }
    
    void inserted(int a,int b)
    {
        ed[++tot].v=b;
        ed[tot].next=firsted[a];
        firsted[a]=tot;
    }
    
    void combine(int x,int y)
    {
        int now=y;
        cir[0]=0;
        while(now!=x)
        {
            cir[++cir[0]]=now;
            now=fa[now];
        }
        cir[++cir[0]]=x;
    
        cirdp[0][0]=cirdp[0][1]=0;
        for(int i=1;i<cir[0];i++)
        {
            cirdp[i][0]=cirdp[i-1][1]+dp[cir[i]][0];
            cirdp[i][1]=cirdp[i-1][0]+dp[cir[i]][1];
            cirdp[i][1]=max(cirdp[i][0],cirdp[i][1]);
        }
        dp[++totpbc][1]=cirdp[cir[0]-1][1];
    
        cirdp[1][0]=cirdp[1][1]=0;
        for(int i=2;i<cir[0]-1;i++)
        {
            cirdp[i][0]=cirdp[i-1][1]+dp[cir[i]][0];
            cirdp[i][1]=cirdp[i-1][0]+dp[cir[i]][1];
            cirdp[i][1]=max(cirdp[i][0],cirdp[i][1]);
        }
        if (cir[0]==2) dp[totpbc][0]=dp[1][0];
        else dp[totpbc][0]=cirdp[cir[0]-2][1]+dp[cir[1]][0]+dp[cir[cir[0]-1]][0];
        dp[totpbc][1]=max(dp[totpbc][1],dp[totpbc][0]);
    
        inserted(x,totpbc);
        for(int i=1;i<cir[0];i++)
            inserted(totpbc,cir[i]);
    }
    
    void tarjan(int v,int laste)
    {
        vis[v]=inst[v]=1;
        low[v]=dfn[v]=++tim;
        st[++top]=v;
        int now=top;
        for(int i=first[v];i;i=e[i].next)
            if (e[i].id!=laste)
            {
                if (!vis[e[i].v])
                {
                    fa[e[i].v]=v;
                    fae[e[i].v]=e[i].id;
                    tarjan(e[i].v,e[i].id);
                    if (low[e[i].v]>dfn[v])
                    {
                        top--;
                        inst[e[i].v]=0;
                        inserted(v,e[i].v);
                    }
                    if (low[e[i].v]==dfn[v])
                    {
                        for(int i=top;i>now;i--)
                            inst[st[i]]=0;
                        top=now;
                    }
                    low[v]=min(low[v],low[e[i].v]);
                }
                else if (inst[e[i].v]) low[v]=min(low[v],dfn[e[i].v]);
            }
        for(int i=first[v];i;i=e[i].next)
            if (fae[e[i].v]!=e[i].id&&dfn[v]<dfn[e[i].v]) combine(v,e[i].v);
        for(int i=firsted[v];i;i=ed[i].next)
        {
            dp[v][0]+=dp[ed[i].v][1];
            dp[v][1]+=dp[ed[i].v][0];
        }
        dp[v][1]+=val[v];
        dp[v][1]=max(dp[v][1],dp[v][0]);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            insert(a,b,i),insert(b,a,i);
        }
        for(int i=1;i<=n;i++)
            scanf("%lld",&val[i]);
    
        totpbc=n;
        tot=0;
        fa[1]=0;
        tarjan(1,0);
        printf("%lld",dp[1][1]);
    
        return 0;
    }
  • 相关阅读:
    Sprng Data JPA与hibernate的关系
    Exception in thread "main" java.io.FileNotFoundException: d:xxx.txt (拒绝访问。)
    Telnet测试BIO Socket
    计算机网络篇
    Postman测试接口发现时间少8个小时?添加这两行代码就解决!
    匿名内部类
    解决线程安全的三种方法
    equals和hashcode的区别
    postman测试springsecurity 登录鉴权,获取Cookie后进行其他接口测试
    (链表)求相交链表交点
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793401.html
Copyright © 2011-2022 走看看