当时写题目时的两个坑
- 有向边的指向是从to->i;如果建边写成addedge(i, to)是不能生成树形结构的(因为讨厌to的骑士可能不止i,会产生一个节点存在多条入边的情况)!
- 题目没有说明骑士的边构成连通图,所以他们的连通块不一定只有一个(即环可能不止一个)!
代码:
#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;
}