• 创世纪 BZOJ3037 & [Poi2004]SZP BZOJ2068


    分析:

    树形DP中的一种,基环树DP

    针对每一个环跑DP,f[i],g[i]分别表示选或者不选,之后我们注意每次遍历的时候,不要重复遍历。

    附上代码:

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #include <cstring>
    #include <cstdlib>
    using namespace std;
    #define N 1000005
    struct node
    {
        int to,next;
    }e[N<<1];
    int head[N],cnt,f[N],g[N],fa[N],now,n,ra[N],rb[N];
    void add(int x,int y)
    {
        e[cnt].to=y;
        e[cnt].next=head[x];
        head[x]=cnt++;
        return ;
    }
    int find(int x){if(fa[x]==x)return x;return fa[x]=find(fa[x]);}
    void dfs(int x)
    {
        int minn=1<<30;
        g[x]=0;
        for(int i=head[x];i!=-1;i=e[i].next)
        {
            int to1=e[i].to;
            if(to1!=now)dfs(to1);
            g[x]+=max(f[to1],g[to1]);
            minn=min(minn,max(f[to1],g[to1])-g[to1]);
        }
        f[x]=g[x]+1-minn;
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        scanf("%d",&n);int cnt=0;
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            if(find(x)!=find(i))
            {
                add(x,i);
                fa[fa[x]]=fa[i];
            }else ra[++cnt]=x,rb[cnt]=i;
        }
        int ans=0;
        for(int i=1;i<=cnt;i++)
        {
            dfs(ra[i]);now=ra[i];
            dfs(rb[i]);
            int t=f[rb[i]];
            f[ra[i]]=g[ra[i]]+1;
            dfs(rb[i]);ans+=max(t,g[rb[i]]);
        }
        printf("%d
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    Canvas技术
    线段树树状数组小结
    html5 Canvas元素
    ccpc网络邀请赛部分
    2020杭电多校
    JavaFx 绘制图形和文本(笔记)
    P4094 [HEOI2016/TJOI2016]字符串(二分+多种数据结构)
    L3-021 神坛 (30分) (计算几何最小三角形面积)
    10月28日G、H、I题
    出栈序列的合法性 (25分) 之树状数组玄学做法
  • 原文地址:https://www.cnblogs.com/Winniechen/p/9080047.html
Copyright © 2020-2023  润新知