1. 程式人生 > 實用技巧 >CF1388C Uncle Bogdan and Country Happiness (dfs)

CF1388C Uncle Bogdan and Country Happiness (dfs)

Practice link:https://codeforces.ml/problemset/problem/1388/C

題意:由 m 個人每個人居住在某一個城市,每個人一開始都在 1 號城市,每個人有不同的心情,1表示好心情,0表示壞心情,每個人在回家途中可以由 1 變成 0 ,但不能由 0 變成 1,告訴你在某個城市經過這個城市的人的心情值總和sum[ i ],問你是否合法。

思路:首先,我們假設經過城市 i 擁有好辛勤的人為 good[ i ],擁有壞心情的人為 bad[ i ],設經過這個點的人數為 num[ i ],則good[ i ] + bad[ i ] = num[ i ],good[ i ] - bad[ i ] =sum[ i ],

那麼兩式聯立,得到 2*good[ i ] = num[ i ] + sum[ i ],因此得到條件一 :good[ i ] % 2 == 0 。再看條件,心情只能由 1 變成 0,不能由 0 變成 1,因此條件二:某一點的子樹上的好心情的數量小於等於該點子樹上的good[ i ]。還有一個就是:good [ i ]>=0 且 good[ i ]<=num[ i ]。

對於這些條件,我們可以通過dfs 去求得某一點上的這些值,去判斷是否合法即可。

其中有一個求以某一個結點為根的所有子節點權值和的操作,記錄一下

程式碼:

 1 #include<bits/stdc++.h>
 2
#define ll long long 3 #define MOD 1e9+7 4 #define INF 0x3f3f3f3f 5 #define mem(a,x) memset(a,x,sizeof(a)) 6 #define _for(i,a,b) for(int i=a; i< b; i++) 7 #define _rep(i,a,b) for(int i=a; i<=b; i++) 8 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 9 10 using namespace std;
11 const int MAXN = 100005; 12 int n,m; 13 int h[MAXN],p[MAXN],sum[MAXN],good[MAXN]; 14 vector<int>g[MAXN]; 15 int flag; 16 void dfs(int u,int fa) 17 { 18 if(flag==0)return; 19 sum[u]=p[u]; 20 int s=0; //good人數之和 21 for(int i=0;i<g[u].size();i++){ 22 int v=g[u][i]; 23 if(v==fa)continue; 24 dfs(v,u); 25 sum[u]+=sum[v]; 26 s+=good[v]; 27 } 28 int temp=sum[u]+h[u]; 29 if(temp%2!=0){flag=0;return;} 30 good[u]=temp/2; 31 if(good[u]>sum[u]||good[u]<0){flag=0;return;} 32 if(s>good[u]){flag=0;return;} 33 } 34 35 int main() 36 { 37 int T; 38 cin>>T; 39 while(T--){ 40 scanf("%d %d",&n,&m); 41 for(int i=1;i<=n;i++){ 42 scanf("%d",&p[i]); 43 g[i].clear(); 44 sum[i]=0; 45 good[i]=0; 46 } 47 for(int i=1;i<=n;i++){ 48 scanf("%d",&h[i]); 49 } 50 for(int i=1;i<n;i++){ 51 int a,b; 52 scanf("%d %d",&a,&b); 53 g[a].push_back(b); 54 g[b].push_back(a); 55 } 56 flag=1; 57 dfs(1,0); 58 if(flag)cout<<"YES"<<endl; 59 else cout<<"NO"<<endl; 60 } 61 return 0; 62 }