• BZOJ_2068_[Poi2004]SZP_树形DP


    BZOJ_2068_[Poi2004]SZP_树形DP

    Description

    Byteotian 中央情报局 (BIA) 雇佣了许多特工. 他们每个人的工作就是监视另一名特工. Byteasar 国王需要进行一次秘密行动,所以他要挑选尽量多的信得过的特工. 但是这项任务是如此的机密以至于所有参加行动的特工都必须至少被另一名没有参加任务的特工所监视( 就是说如果某个特工参加了行动,那么原先监视他的那些特工中至少要有一个没有参加进行动). 给出监视任务的详情,要求计算最多能有多少个特工参与其中.

    Input

    第一行只有一个整数, n – 特工的总数, 2 <= n <= 1000000. 特工从1 到 n编号. 接下来n行每行一个整数ak 表示特工k将要监视特工ak , 1 <= k <= n, 1 <= ak <= n, ak <> k.

    Output

    打印一个数,最多能有多少特工参加入这个任务.

    Sample Input

    6
    2
    3
    1
    3
    6
    5

    Sample Output

    3

    HINT


     基环树DP,把环断开,让一个强制不选,然后跑两次DP。

    每次DP的求法类似一个最小支配集。

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 1000050
    int head[N],to[N<<1],nxt[N<<1],cnt,fa[N],root[N],kill[N],n,f[N],g[N],le;
    inline void add(int u,int v) {
        to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
    }
    int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
    void dfs(int x) {
        int i,minn=100000,ok=0,maxx=0;
        f[x]=1; g[x]=0;
        for(i=head[x];i;i=nxt[i]) {
            if(to[i]!=le) 
                dfs(to[i]);
                g[x]+=max(g[to[i]],f[to[i]]);
                maxx+=max(g[to[i]],f[to[i]]);
                if(g[to[i]]>=f[to[i]]) ok=1;
                else minn=min(minn,f[to[i]]-g[to[i]]);
             
        }
        if(ok) f[x]+=maxx;
        else f[x]+=maxx-minn;
    }
    int main() {
        scanf("%d",&n);
        int i,x,y,ans=0;    
        for(i=1;i<=n;i++) fa[i]=i;
        for(i=1;i<=n;i++) {
            scanf("%d",&x);
            int dx=find(x),di=find(i);
            if(dx!=di) {
                fa[di]=dx;
                add(x,i);
            }else {
                root[dx]=x; kill[dx]=i;
            }
        }
        for(i=1;i<=n;i++) {
            if(fa[i]==i) {
                dfs(root[i]); le=root[i];
                dfs(kill[i]); int t=f[kill[i]];
                f[root[i]]=g[root[i]]+1;
                dfs(kill[i]);
                ans+=max(t,g[kill[i]]);
            }
        }
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    day06作业
    day04_ATM项目说明书
    ATM+购物车基本思路流程
    装饰器、迭代器、生成器、递归、匿名函数、面向过程编程、三元表达式6
    day05函数部分
    自制七段数码管源码
    字符串格式化
    字符串表示
    格式化输出
    python入门——列表类型、元组、字典类型
  • 原文地址:https://www.cnblogs.com/suika/p/8967677.html
Copyright © 2020-2023  润新知