NC20481. [ZJOI2008]骑士
描述
输入描述
第一行包含一个正整数N,描述骑士团的人数。
接下来N行,每行两个正整数,按顺序描述每一名骑士的战斗力和他最痛恨的骑士。
输出描述
应包含一行,包含一个整数,表示你所选出的骑士军团的战斗力。
示例1
输入:
3 10 2 20 3 30 1
输出:
30
C++11(clang++ 3.9) 解法, 执行用时: 1026ms, 内存消耗: 63032K, 提交时间: 2020-04-01 17:09:45
#include<bits/stdc++.h> #define ll long long #define N 1000005 using namespace std; struct edge { ll to; ll next; }c[N]; ll en,head[N],n,root,v[N]={0},too[N]={0}; ll mark,w[N],f[N],g[N],ans; void add1(ll from,ll to) { c[++en].to=to; c[en].next=head[from]; head[from]=en; } void find_circle(ll x) { v[x]=1; if(v[too[x]]) mark=x; else find_circle(too[x]); } void dfs(ll x) { v[x]=1; f[x]=w[x]; g[x]=0; for(ll i=head[x];i;i=c[i].next) { ll y=c[i].to; if(y!=mark) { dfs(y); g[x]+=max(f[y],g[y]); f[x]+=g[y]; } else f[x]=-(N); } } int main() { scanf("%lld",&n); for(ll i=1;i<=n;i++) { scanf("%lld %lld",&w[i],&too[i]); add1(too[i],i); } for(ll i=1;i<=n;i++) { if(v[i]) continue; find_circle(i); dfs(mark); ll maxn=max(f[mark],g[mark]); mark=too[mark]; root=0; dfs(mark); ans+=max(maxn,max(f[mark],g[mark])); } printf("%lld",ans); }