zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    MATLAB调用VISUAL STUDIO 编写的C++函数
    卡尔曼滤波
    资料(不定时更新)
    20201207-总结
    20201126-1 每周例行报告
    20201120-1 每周例行报告
    作业要求 20201112-1 每周例行报告
    20201105-1 每周例行报告
    作业要求 20201029-1 每周例行报告
    作业要求 20201022-1 每周例行报告
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8886249.html
Copyright © 2011-2022 走看看