树上贪心
对于每个-1,如果有子节点则最大化,无子节点则最小化。 题目大意:给出一棵树,每个节点到根节点的路径上经过的所有点的权值之和,其深度为偶数的节点的信息全部擦除了,也就是用-1表示,让你求最终所有点权之和(要求最小)
具体思路:对于每一个节点,这个点到根节点的权值最小的时候是他的所有的根节点的最小值,然后一路更新上去就可以了,最后求值得时候,我们求父亲节点和子节点之间的差就可以了, 如果差值为负值就是非法情况。
#include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int using namespace std; typedef long long ll; //typedef __int128 lll; const int N=200000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,q; ll ans; ll a[N]; vector<int>G[N]; char str; void dfs(int rt,int m){ if(a[rt]==-1){ ll tmp = INF; for(int v:G[rt])tmp = min(tmp,a[v]); if(tmp==INF) tmp=m; a[rt]=tmp; } if(a[rt]-m<0){ cout<<-1<<endl;//printf("%d",rt); exit(0); } ans += a[rt]-m; for(int v:G[rt]) dfs(v,a[rt]); } int main() { #ifdef DEBUG freopen("input.in", "r", stdin); //freopen("output.out", "w", stdout); #endif scanf("%d",&n); for(int i=2;i<=n;i++){ scanf("%d",&t); G[t].push_back(i); //for(int v:G[t])cout<<v<<t; } for(int i=1;i<=n;i++){ scanf("%I64d",&a[i]); } ans=0; dfs(1,0); cout<<ans<<endl; //cout << "Hello world!" << endl; return 0; }