forked from mpfeifer1/Kattis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnuremberg.cpp
115 lines (94 loc) · 2.41 KB
/
nuremberg.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll inf = (ll)1 << 60;
ll best_dist = inf;
vector<ll> best;
ll total_locs;
ll dfs(ll curr, ll dist, vector<vector<pair<ll,ll>>>& adj, vector<ll>& size, vector<ll>& sub_size, vector<bool>& vis) {
if(vis[curr]) return 0;
vis[curr] = true;
ll res = size[curr] * dist;
for(auto i : adj[curr]) {
ll next = i.first;
ll weight = i.second;
if(!vis[next]) {
res += dfs(next, dist+weight, adj, size, sub_size, vis);
sub_size[curr] += sub_size[next];
}
}
sub_size[curr] += size[curr];
return res;
}
void reroot(ll curr, ll ans, vector<vector<pair<ll,ll>>>& adj, vector<ll>& size, vector<ll>& sub_size, vector<bool>& vis) {
if(vis[curr]) return;
vis[curr] = true;
if(ans < best_dist) {
best.clear();
best_dist = ans;
}
if(ans == best_dist) {
best.push_back(curr+1);
}
for(auto i : adj[curr]) {
ll next = i.first;
ll weight = i.second;
ll new_ans = ans;
ll sub = sub_size[next] * weight;
ll add = (total_locs - sub_size[next]) * weight;
new_ans -= sub;
new_ans += add;
reroot(next, new_ans, adj, size, sub_size, vis);
}
}
void solve() {
best_dist = inf;
best.clear();
total_locs = 0;
ll n;
cin >> n;
// {dest,weight}
vector<vector<pair<ll,ll>>> adj(n);
for(ll i = 0; i < n-1; i++) {
ll a, b, t;
cin >> a >> b >> t;
a--; b--;
t *= 2;
adj[a].push_back({b,t});
adj[b].push_back({a,t});
}
// Read in how many times each node must be visited
vector<ll> size(n,0);
ll m;
cin >> m;
for(ll i = 0; i < m; i++) {
ll a, t;
cin >> a >> t;
a--;
size[a] += t;
total_locs += t;
}
// Calculate all the subtree sizes, and the initial answer
vector<ll> sub_size(n,0);
// Solve the problem for one root
vector<bool> vis(n,false);
ll ans = dfs(0,0,adj,size,sub_size,vis);
// Reroot at any point
vis.clear();
vis.resize(n,false);
reroot(0,ans,adj,size,sub_size,vis);
// Print the answer
cout << best_dist << endl;
sort(best.begin(),best.end());
for(auto i : best) {
cout << i << " ";
}
cout << endl;
}
int main() {
ll cases;
cin >> cases;
while(cases--) {
solve();
}
}