对于某个节点u, 如果整个子树里的人数超过了节点数, 那么显然就要把多余的人移动到点u的父亲处, 而如果人不足, 就需要从u的父亲处拿人过来, 至于u父亲出人够不够, 那么就需要考虑以u的父亲为根的子树了, 所以可以考虑dfs递归处理问题, 对于所有节点, 如果节点上人太多, 多余的人必然要到他父亲那边, 如果没人,必要要从父亲处要人, 所以在每次处理完一颗子树时,根据子树的根的情况, 来修改子树根的父亲的情况即可
// #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #include <limits.h> // #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__ ) #else #define debug(...) #endif #define MEM(x,y) memset(x, y,sizeof x) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; bool vis[10010]; int moves; int n; vector<int> G[10010]; int have[10010]; int solve(int u){ vis[u] = true; int sum = have[u] - 1; for (int i = 0;i < G[u].size();++i){ int v = G[u][i]; if (vis[v]) continue; int w = solve(v); sum += w;//u节点为根的树还需要多少人; moves += abs(w); } return sum; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int icase = 0, t; cin >> t; while(t--){ cin >> n; for (int i = 1;i <= n;++i) G[i].clear(); memset(vis, false,sizeof vis); for (int i = 1;i <= n;++i){ int u, w, num; scanf("%d%d%d",&u, &w, &num); have[u] = w; int v; while(num--){ cin >> v; G[u].push_back(v); G[v].push_back(u); } } moves = 0; solve(1); printf("Case %d: %d\n", ++icase, moves); } return 0; }
lightoj1219Mafia
最新推荐文章于 2017-08-23 12:59:51 发布