• bzoj1040: [ZJOI2008]骑士


    本来今天想学基环树的

    认真看一看,这不就是弱化的仙人掌嘛

    然后,就直接仙人掌上DP咯(蒟蒻不是很会调了一晚上。。。)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    
    struct node
    {
        int x,y,next;
    }a[2100000];int len,last[1100000];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    LL ft[1100000],f[2][1100000];
    int z,dfn[1100000],fa[1100000];
    bool v[1100000];//是否在仙人掌中
    void DP(int rt,int x)//只需要更新rt 
    {
        LL g[2][2];
        int pre=0,now=1;
        g[now][0]=g[now][1]=0;
        for(int i=x;i!=rt;i=fa[i])
        {
            swap(pre,now);
            g[now][0]=max(g[pre][0],g[pre][1])+f[0][i];
            g[now][1]=g[pre][0]+f[1][i];
        }
        f[0][rt]+=max(g[now][0],g[now][1]);
        //不取rt 
        
        pre=0,now=1;
        g[now][0]=g[now][1]=0;
        for(int i=x;i!=rt;i=fa[i])
        {
            swap(pre,now);
            g[now][0]=max(g[pre][0],g[pre][1])+f[0][i];
            if(i==x||fa[i]==rt)g[now][1]=0;
            else g[now][1]=g[pre][0]+f[1][i];
        }
        f[1][rt]+=max(g[now][0],g[now][1]);
        //取rt 
    }
    int h[1100000];
    void cactus(int x)
    {
        dfn[x]=++z;
        f[0][x]=0;f[1][x]=ft[x];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(dfn[y]==0)
                fa[y]=x, cactus(y);
        }
        
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(fa[x]!=y)
            {
                if(dfn[y]<dfn[x])
                {
                    h[y]=x;
                    for(int i=x;i!=y;i=fa[i])v[i]=true;
                }
                else if(v[y]==false)
                {
                    f[0][x]+=max(f[0][y],f[1][y]);
                    f[1][x]+=f[0][y];
                }
            }
        }
        if(h[x]!=-1)DP(x,h[x]);
    }
    
    //-------------------------------
    
    int hate[1100000];
    int main()
    {
        int n,x;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%d",&ft[i],&x);
            hate[i]=x;
            if(hate[x]!=i)
                ins(i,x), ins(x,i);
        }
        
        LL ans=0;
        memset(dfn,0,sizeof(dfn));
        memset(v,false,sizeof(v));
        memset(h,-1,sizeof(h));
        for(int i=1;i<=n;i++)
            if(dfn[i]==0)
            {
                cactus(i);
                ans+=max(f[0][i],f[1][i]);
            }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    第一个爬虫和测试
    乒乓球比赛模拟分析
    appium入门
    node安装
    自动化测试---selenium
    自动化测试---元素定位
    Shell脚本
    Shell脚本的编写
    Linux安装jdk,mysql,tomcat
    Linux的简单使用
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8886249.html
Copyright © 2020-2023  润新知