题目链接:http://codeforces.com/problemset/problem/682/C
分析:存图,用dfs跑一遍,详细见注释
1 #include<iostream> 2 #include<sstream> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<string> 6 #include<cstring> 7 #include<algorithm> 8 #include<functional> 9 #include<iomanip> 10 #include<numeric> 11 #include<cmath> 12 #include<queue> 13 #include<vector> 14 #include<set> 15 #include<cctype> 16 #define PI acos(-1.0) 17 const int INF = 0x3f3f3f3f; 18 const int NINF = -INF - 1; 19 const int maxn = 1e5 + 5; 20 typedef long long ll; 21 using namespace std; 22 int n; 23 int arr[maxn]; 24 struct edge 25 { 26 int to, cost; 27 }; 28 vector<edge> G[maxn]; 29 int dfs(int x, int y, ll dis)//x为dfs当前进行到的节点,y为x节点的父亲节点,dis记录从根结点到当前x点的距离 30 { 31 if (dis > arr[x]) return 0;//如果触发到距离大于节点权值就返回0 32 int ans = 1;//ans记录有几个剩余节点,每一个节点的ans只有0或1,0即舍去 33 for (int i = 0; i < G[x].size(); ++i) 34 { 35 if (G[x][i].to == y) continue;//防止dfs返回到x节点的父亲节点 36 ans += dfs(G[x][i].to, x, max(G[x][i].cost + dis, 0ll));//因为题目中存在负权边,如果累加负数,显然会抵消正数造成答案出错 37 }//反证:例如,1-3的dis为-10,如果累加了这个-10,3-4的为5,而4权值为3,那么dis1-4为-5小于3,节点4不需要删除,但这显然是错的 38 return ans; 39 } 40 int main() 41 { 42 cin >> n; 43 for (int i = 1; i <= n; ++i) 44 cin >> arr[i]; 45 for (int i = 2; i <= n; ++i) 46 { 47 int to, cost; 48 cin >> to >> cost; 49 G[i].push_back(edge{to, cost});//存图 50 G[to].push_back(edge{i, cost}); 51 } 52 int ans = dfs(1, -1, 0);//从根节点1开始进行dfs 53 cout << n - ans; 54 return 0; 55 }