zoukankan      html  css  js  c++  java
  • 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);
    }
    
  • 相关阅读:
    centos 网络开启
    ubuntu server 服务器部署(二) mysql 安装配置手记
    ubuntu server 服务器部署(一) jdk 安装配置手记
    网络管理
    磁盘配额
    创建raid0
    创建raid5
    逻辑卷快照
    LVM(逻辑卷)
    1.计算机基础
  • 原文地址:https://www.cnblogs.com/suika/p/8967677.html
Copyright © 2011-2022 走看看