P2607 [ZJOI2008] 骑士

P2607


当时写题目时的两个坑

  1. 有向边的指向是从to->i;如果建边写成addedge(i, to)是不能生成树形结构的(因为讨厌to的骑士可能不止i,会产生一个节点存在多条入边的情况)!
  2. 题目没有说明骑士的边构成连通图,所以他们的连通块不一定只有一个(即环可能不止一个)!

代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e6 + 7;

int r1, r2, vis[N], val[N];
ll f[N][2], sum = 0;

int head[N], tot;
struct Edge{
    int nt, to;
}edge[N];

void addedge(int u, int v){
    edge[++ tot].nt = head[u];
    head[u] = tot;
    edge[tot].to = v;
}

void find(int u, int rt){
    vis[u] = 1;
    for(int i = head[u]; i ;i = edge[i].nt){
        int v = edge[i].to;
        if(v == rt){
            r1 = u, r2 = v;
            return;
        }
        if(vis[v]) continue;
        find(v, rt);
    }
}

ll dfs(int u, int rt){
    f[u][0] = 0, f[u][1] = val[u];
    for(int i = head[u]; i ;i = edge[i].nt){
        int v = edge[i].to;
        if(v == rt) continue;
        dfs(v, rt);
        f[u][0] += max(f[v][0], f[v][1]);
        f[u][1] += f[v][0];
    }
    return f[u][0];
}

int main(){
    int n;
    scanf("%d", &n);
    for(int i = 1;i <= n;i ++){
        int w, to;
        scanf("%d%d", &w, &to);
        val[i] = w;
        addedge(to, i);
    }
    for(int i = 1;i <= n;i ++){
        if(vis[i]) continue;
        r1 = r2 = 0;
        find(i, i);
        if(r1 == 0) continue;
        ll re1 = dfs(r1, r1);
        ll re2 = dfs(r2, r2);
        sum += max(re1, re2);
    }
    printf("%lld", sum);
    return 0;
}
posted @ 2022-11-20 19:59  feuerwerk  阅读(18)  评论(0)    收藏  举报