zoukankan      html  css  js  c++  java
  • 骑士 树上+环上dp

    这题我最大的收获是不要轻易相信网上的blog的题解...

    环上dp 应该是两维,不能一维 (一下午的崩溃啊)

    先求出环上每个点选和不选的最大值

    再枚举环上那个点选不选(枚举相邻两个就行)

    进行dp

    /*
    我现在只想日死那个一维f[]的人
    环上dp需要f[N][2]...
     */
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    inline int read()
    {
        char q=getchar();int ans=0,flag=1;
        while(q<'0'||q>'9'){if(q=='-')flag=-1;q=getchar();}
        while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
        return ans*flag;
    }
    const int N=1000006;
    inline ll maxn(ll a,ll b){return a>b?a:b;}
    struct son
    {
        int v,next;
    }a1[N*2];
    int first[N*2],e;
    void addbian(int u,int v)
    {
        a1[e].v=v;
        a1[e].next=first[u];
        first[u]=e++;
    }
    
    int n;
    int nx[N],ind[N];
    int v[N];
    ll g[N][2];
    int dfn[N],low[N],zhan[N],he,tim,dui[N],sum,size[N];
    bool flag[N];
    bool vis[N];
    
    ll t[N][2];
    int con;
    ll f[N][2];
    
    ll get(int begg,int endd)
    {
        con=0;
        for(int i=begg;i!=endd;i=nx[i])
        {
            ++con;
            vis[i]=1;
            t[con][0]=g[i][0];
            t[con][1]=g[i][1];
        }
        f[0][0]=f[0][1]=0;
        f[1][0]=t[1][0];f[1][1]=t[1][1];
        for(int i=2;i<=con;++i)
        {
            f[i][1]=f[i-1][0]+t[i][1];
            f[i][0]=maxn(f[i-1][1],f[i-1][0])+t[i][0];
        }
        return maxn(f[con][0],f[con][1]);
    }
    
    int fa[N];
    void dp(int x)
    {
        g[x][0]=0;g[x][1]=v[x];
        int temp;
        for(int i=first[x];i!=-1;i=a1[i].next)
        {
            temp=a1[i].v;
            if(temp==fa[x]||size[dui[temp]]>1)
                continue;
            fa[temp]=x;
            dp(temp);
            g[x][0]+=maxn(g[temp][0],g[temp][1]);
            g[x][1]+=g[temp][0];
        }
    }
    
    void tarjan(int x)
    {
        dfn[x]=low[x]=++tim;
        zhan[++he]=x;flag[x]=1;
        int temp;
        for(int i=first[x];i!=-1;i=a1[i].next)
        {
            temp=a1[i].v;
            if(dfn[temp]==-1)
            {
                tarjan(temp);
                low[x]=min(low[x],low[temp]);
            }
            else
                if(flag[temp])
                    low[x]=min(low[x],low[temp]);
        }
        if(low[x]==dfn[x])
        {
            ++sum;
            while(1)
            {
                temp=zhan[he--];flag[temp]=0;
                dui[temp]=sum;
                ++size[sum];
                if(temp==x)
                    break;
            }
        }
    }
    
    ll work()
    {
        ll ans=0,t1,t2;
    
        he=0;
        for(int i=1;i<=n;++i)
            if(dfn[i]==-1)
                tarjan(i);
    
        for(int i=1;i<=n;++i)
            if(size[dui[i]]>1)
            {
                fa[i]=-1;
                dp(i);
            }
    
        for(int i=1;i<=n;++i)
            if(size[dui[i]]>1&&!vis[i])
            {
                t1=g[i][0]+get(nx[i],i);
                t2=g[nx[i]][0]+get(nx[nx[i]],nx[i]);
                ans+=maxn(t1,t2);
            }
        return ans;
    }
    
    int main(){
    
        //freopen("in.in","r",stdin);
    
        mem(first,-1);
        mem(dfn,-1);
    
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d%d",&v[i],&nx[i]);
            ++ind[nx[i]];
            addbian(nx[i],i);
        }
        cout<<work();
    }
    AA

    本来还觉得这道题跟maf枪战一样呢

    还应用了贪心+一些之前做过的题的技巧,打了半天wa了6个点....

  • 相关阅读:
    高可靠JAVA项目
    C语言JS引擎
    星际争霸,FF反作弊对战平台
    【转】ffluos编译
    〓经典文字武侠游戏 书剑 书剑江湖自由度超高!公益服!〓
    全局解释器锁GIL
    创建多线程Thread
    线程的简述Thread
    进程池的回调函数callback
    进程池的同步与异步用法Pool
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7673713.html
Copyright © 2011-2022 走看看