• bzoj1040: [ZJOI2008]骑士


    题目链接

    bzoj1040: [ZJOI2008]骑士

    题解

    讨厌关系出度为0,可能有环,并且每个联通块内只有一个环 没有自环
    构成基环树森林
    选取骑士不能去相邻的
    考虑将一个联通块中的环断开,这样就构成一棵树,对于断开的边相连的点分别不取,进行dp
    答案就是每个联通块的贡献和

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    #define int long long
    const int maxn = 1000007;
    inline int read () {
        int x = 0,f = 1;
        char c = getchar ();
        while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
        while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
        return x*f;
    }
    struct node{
        int v,next;
    }edge[maxn << 1];
    int head[maxn],num = 1;
    bool vis[maxn];
    inline void Add_edge(int u,int v) { edge[++ num].v = v,edge[num].next = head[u];head[u] = num; }
    int son [maxn] ,Val [maxn]; 
    int n,father[maxn],R1,R2,Flag,val; 
    void Find_Link(int x,int fa) {
        vis[x] = 1;
        for(int i = head[x];i;i = edge[i].next) {
            int v = edge[i].v;
            if(v == fa) continue;
            if(vis[v]) {
                R1 = x;R2 = v;Flag = i;
            }
            else Find_Link(v,x);
        }
    }
    int dp[maxn][2];
    void  dfs(int x,int fa) {
        dp[x][1] += Val[x];
        for(int i = head[x];i;i = edge[i].next) {
            int v = edge[i].v;
            if(v == fa || i == Flag || (i^1) == Flag) continue;
            dfs(v,x);
            dp[x][1] += dp[v][0];
            dp[x][0] += std::max(dp[v][1],dp[v][0]);
        }
    }
    main () {
        n = read();
        for(int a,i = 1;i <= n;++ i) {
            Val[i] = read();
            Add_edge(a = read(),i);
            Add_edge(i,a);
        }
        int ans = 0 ;
        for(int tmp,i = 1;i <= n;++ i) {
            if(!vis[i]) {
                R1 = R2 = 0;
                Find_Link(i,i);
                if(R1 == R2) { 
                    dfs(i,i);
                    ans += std::max(dp[i][0],dp[i][1]);
                    continue;
                }
                dfs(R1,R1);tmp = dp[R1][0];
                memset(dp,0,sizeof dp);
                dfs(R2,R2);ans += std::max(tmp,dp[R2][0]);
            }
        }
        printf("%lld
    ",ans);
    //	return 0;
    }
        
    
  • 相关阅读:
    jQuery实现 自动滚屏操作
    jQuery实现全选、全不选以及反选操作
    读曾国藩
    把时间当作朋友 之感知时间
    把时间当作朋友4未知永远存在
    Android N 设置中语言列表介绍
    如何编译ICU资源
    idea常用快捷键
    shell 笔记
    Json笔记
  • 原文地址:https://www.cnblogs.com/sssy/p/8705581.html
Copyright © 2020-2023  润新知