1. 程式人生 > >騎士 HYSBZ - 1040(基環樹+樹形dp)

騎士 HYSBZ - 1040(基環樹+樹形dp)

inpu c++ desc 匯聚 signed long ons clu inf

 Z國的騎士團是一個很有勢力的組織,幫會中匯聚了來自各地的精英。他們劫富濟貧,懲惡揚善,受到社會各
界的贊揚。最近發生了一件可怕的事情,邪惡的Y國發動了一場針對Z國的侵略戰爭。戰火綿延五百裏,在和平環境
中安逸了數百年的Z國又怎能抵擋的住Y國的軍隊。於是人們把所有的希望都寄托在了騎士團的身上,就像期待有一
個真龍天子的降生,帶領正義打敗邪惡。騎士團是肯定具有打敗邪惡勢力的能力的,但是騎士們互相之間往往有一
些矛盾。每個騎士都有且僅有一個自己最厭惡的騎士(當然不是他自己),他是絕對不會與自己最厭惡的人一同出
征的。戰火綿延,人民生靈塗炭,組織起一個騎士軍團加入戰鬥刻不容緩!國王交給了你一個艱巨的任務,從所有
的騎士中選出一個騎士軍團,使得軍團內沒有矛盾的兩人(不存在一個騎士與他最痛恨的人一同被選入騎士軍團的
情況),並且,使得這支騎士軍團最具有戰鬥力。為了描述戰鬥力,我們將騎士按照1至N編號,給每名騎士一個戰
鬥力的估計,一個軍團的戰鬥力為所有騎士的戰鬥力總和。

Input

  第一行包含一個正整數N,描述騎士團的人數。接下來N行,每行兩個正整數,按順序描述每一名騎士的戰鬥力
和他最痛恨的騎士。

Output

  應包含一行,包含一個整數,表示你所選出的騎士軍團的戰鬥力。

Sample Inpu t3 10 2 20 3 30 1

Sample Output

30

Hint

N ≤ 1 000 000,每名騎士的戰鬥力都是不大於 1 000 000的正整數。

基環樹模板題

#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof(a))
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define
rep(i, a, n) for(int i=a; i<n; i++) #define lap(i, a, n) for(int i=n; i>=a; i--) #define lep(i, a, n) for(int i=n; i>a; i--) #define rd(a) scanf("%d", &a) #define rlld(a) scanf("%lld", &a) #define rc(a) scanf("%c", &a) #define rs(a) scanf("%s", a) #define pd(a) printf("%d\n", a); #define
plld(a) printf("%lld\n", a); #define pc(a) printf("%c\n", a); #define ps(a) printf("%s\n", a); #define MOD 2018 #define LL long long #define ULL unsigned long long using namespace std; const int maxn = 1e6+10, INF = 0x7fffffff; int n, cnt, not_pass, s, t; LL a[maxn], dp[maxn][2]; int vis[maxn], head[maxn]; struct node { int u, v, next; }Node[maxn<<1]; void add_(int u, int v) { Node[cnt].u = u; Node[cnt].v = v; Node[cnt].next = head[u]; head[u] = cnt++; } void add(int u, int v) { add_(u, v); add_(v, u); } void dfs(int u, int pa) { vis[u] = 1; for(int i=head[u]; i!=-1; i=Node[i].next) { node e = Node[i]; if(e.v == pa) continue; if(!vis[e.v]) dfs(e.v, u); else { not_pass = i; s = u; t = e.v; } } } void treedp(int u, int fa) { dp[u][1] = a[u], dp[u][0] = 0; for(int i=head[u]; i!=-1; i=Node[i].next) { node e = Node[i]; if(e.v == fa) continue; if(i == not_pass || i == (not_pass^1)) continue; treedp(e.v, u); dp[u][0] += max(dp[e.v][1], dp[e.v][0]); dp[u][1] += dp[e.v][0]; } } void init() { mem(head, -1); mem(vis, 0); cnt = 0; } int main() { init(); rd(n); int v; rap(i, 1, n) { rlld(a[i]), rd(v); add(i, v); } LL res = 0; rap(i, 1, n) { if(vis[i]) continue; dfs(i, -1); treedp(s, -1); LL tmp = dp[s][0]; treedp(t, -1); res += max(tmp, dp[t][0]); } plld(res); return 0; }

騎士 HYSBZ - 1040(基環樹+樹形dp)