Codeforces 1099 D. Sum in the tree-構造最小點權和有根樹 貪心+DFS(Codeforces Round #530 (Div. 2))
Mitya has a rooted tree with nn vertices indexed from 11 to nn, where the root has index 11. Each vertex vv initially had an integer number
Then Mitya erased all numbers avav, and by accident he also erased all values svsv for vertices with even depth (vertices with even hvhv). Your task is to restore the values avav for every vertex, or determine that Mitya made a mistake. In case there are multiple ways to restore the values, you‘re required to find one which minimizes the total sum of values
The first line contains one integer nn — the number of vertices in the tree (2≤n≤1052≤n≤105). The following line contains integers p2p2, p3p3, ... pnpn, where pipi stands for the parent of vertex with index ii in the tree (1≤pi<i1≤pi<i). The last line contains integer values s1s1, s2s2, ..., snsn (−1≤sv≤109−1≤sv≤109), where erased values are replaced by −1−1.
OutputOutput one integer — the minimum total sum of all values avav in the original tree, or −1−1 if such tree does not exist.
Examples input Copy5 1 1 1 1 1 -1 -1 -1 -1output Copy
1input Copy
5 1 2 3 1 1 -1 2 -1 -1output Copy
2input Copy
3 1 2 2 -1 1output Copy
-1
題意就是給你一個有根樹,然後給你每個節點的父親,然後給你每個節點到根節點的點權之和,然後就是偶數深度的節點的到根節點的點權之和被抹去了,是-1,讓你將這個樹還原,然後求出所有節點的最小點權之和。
因為是隔一層就斷了,所以直接直接給偶數深度節點爸爸賦值他兒子的值中最小的那個,然後,兒子-爸爸的值算出每個點的點權,最後加起來就可以了。如果節點的值是負數,就是不滿足條件的,直接-1輸出就可以了。我寫的時候,wa了好久,搞不清楚為什麽,不用開long long吧,我不開會wa,然後就是如果一個節點是直接連接根節點的,他沒有兒子,那麽我們可以給他賦值為0,我這裏寫早了,寫到dfs出來時每個節點的點權之前了,這樣算出來的肯定是不對的,就是直接0-根節點的權值,肯定是錯的,當時想的是算完之後再處理這些特殊的點,但是手抖寫的時候寫挫了,改了就過了。
代碼:
1 //D 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<algorithm> 7 #include<cstdlib> 8 using namespace std; 9 typedef long long ll; 10 const int inf=0x3f3f3f3f; 11 const int maxn=2e5+10; 12 13 struct node{ 14 int to,val,next; 15 }edge[maxn<<1]; 16 17 int head[maxn<<1],dep[maxn],fa[maxn][30],cnt; 18 int dis[maxn]; 19 20 void add(int x,int y,int v){edge[++cnt].to=y,edge[cnt].val=v,edge[cnt].next=head[x],head[x]=cnt;}//存圖 21 22 void dfs(int u,int fath) 23 { 24 dep[u]=dep[fath]+1; 25 for(int i=head[u];i;i=edge[i].next){ 26 int v=edge[i].to,w=edge[i].val; 27 if(v!=fath){ 28 dis[v]=w; 29 if(dep[u]%2==0){ 30 dis[u]=min(dis[u],dis[v]);//找子節點的值的最小值 31 } 32 } 33 } 34 for(int i=head[u];i;i=edge[i].next){ 35 int v=edge[i].to,w=edge[i].val; 36 if(v!=fath){ 37 dfs(v,u); 38 if(dis[v]!=inf)//如果不是特殊節點 39 dis[v]=dis[v]-dis[u];//當前點的點權就是自己-爸爸的 40 } 41 } 42 } 43 44 int a[maxn],b[maxn]; 45 46 int main() 47 { 48 int n; 49 cin>>n; 50 for(int i=2;i<=n;i++) 51 cin>>a[i]; 52 for(int i=1;i<=n;i++){ 53 cin>>b[i]; 54 if(b[i]==-1) b[i]=inf; 55 } 56 for(int i=2;i<=n;i++){ 57 add(a[i],i,b[i]); 58 add(i,a[i],b[i]); 59 } 60 dis[1]=b[1]; 61 dfs(1,0); 62 for(int i=1;i<=n;i++){ 63 if(dis[i]==inf) dis[i]=0;//如果是特殊節點,處理完還是沒確定值的,就賦值為0 64 } 65 // for(int i=1;i<=n;i++) 66 // cout<<dis[i]<<endl; 67 ll ans=0; 68 int flag=0; 69 for(int i=1;i<=n;i++){ 70 if(dis[i]<0){ 71 flag=1;break; 72 } 73 ans+=dis[i]; 74 } 75 if(flag==0) cout<<ans<<endl; 76 else cout<<-1<<endl; 77 } 78 79 /* 80 10 81 1 1 1 1 2 3 4 5 1 82 3 -1 -1 -1 -1 3 3 3 3 -1 83 84 3 85 */
Codeforces 1099 D. Sum in the tree-構造最小點權和有根樹 貪心+DFS(Codeforces Round #530 (Div. 2))