Solution
Let s u m sum sum be the sum of all values of points, assume we can divide this tree to k k k partitions, then the s u b s u m subsum subsum of each partition equals to s u m / k sum / k sum/k, this implies that k ∣ s u m k | sum k∣sum
The range of k k k is [ 1 , N ] [1, N] [1,N] satisfying k ∣ s u m k | sum k∣sum simultaneously, so all valid values of k k k is the factors of s u m sum sum, and less than or equal to N N N. O ( s q r t ( s u m ) ) = 1000 O( sqrt(sum)) = 1000 O(sqrt(sum))=1000.
Now, the question is, given a k k k, check if it is workable which is equivalent to whether would divide this tree to partitions with the same value s u m / k sum / k sum/k (emitting whether the number of partitions equals to k k k, due to it’s implied).
So, given a
s
u
b
s
u
m
=
s
u
m
/
k
subsum = sum / k
subsum=sum/k, if we can divide this tree to some partitions that with the same value of
s
u
b
s
u
m
subsum
subsum.
Suppose these partitions are
T
1
,
T
2
,
.
.
.
,
T
k
T_1, T_2, ..., T_k
T1,T2,...,Tk, for a partition
T
i
T_i
Ti, suppose
x
x
x is a point within it, this partition
T
i
T_i
Ti may contains some parent-nodes of
x
x
x partially, and also contains some son-nodes of
x
x
x partially.
On other words,
T
i
T_i
Ti may be not a simple-path, it may have several endpoints. So,
T
i
T_i
Ti can not be recorded when processing the DFS. This is the pivot for solving this problem.
The importance is, there must exists a T i T_i Ti that is a sub-tree, while a sub-tree can be recorded within a DFS (sub-tree is composed of one root-points and its all son-points).
Let the initial tree is
T
r
Tr
Tr, when we get the
T
i
T_i
Ti (which is a sub-tree for
T
r
Tr
Tr), then we remove it from
T
r
Tr
Tr, then the new tree becomes
T
r
1
Tr1
Tr1, it has
k
−
1
k-1
k−1 partitions.
This rule also effects in
T
r
1
Tr1
Tr1, that there also exists a
T
j
T_j
Tj that is a sub-tree for
T
r
1
Tr1
Tr1 (not for
T
r
Tr
Tr).
The detail algorithm is, when we are doing DFS, for the current point C C C, get it value s s s of this sub-tree (the value of C C C plus all the DFS-return of its son-points), if equals to s u b s u m subsum subsum, then remove this sub-tree, return 0 0 0 to DFS-return; otherwise, it must connect to his parent, so return s s s.
Code
//{ Graph-Build
static constexpr int Graph_point_count_ = 20005, Graph_edge_count_ = 40005;
int Graph_head[ Graph_point_count_], Graph_ver[ Graph_edge_count_], Graph_nex[ Graph_edge_count_];
int Graph_edge_index;
inline void Graph_init(){
memset( Graph_head, -1, sizeof( Graph_head));
Graph_edge_index = 0;
}
inline void Graph_addEdge( int _from, int _to){
// Graph_wth[ Graph_edge_index] = _wth;
Graph_ver[ Graph_edge_index] = _to;
Graph_nex[ Graph_edge_index] = Graph_head[ _from];
Graph_head[ _from] = Graph_edge_index ++;
}
//} Graph-Build
class Solution {
public:
vector< int> A;
int Sub;
int Dfs( int _cur, int _fa){
int sum = A[ _cur];
for( int j, i = Graph_head[ _cur]; ~i; i = Graph_nex[ i]){
j = Graph_ver[ i];
if( j == _fa){ continue;}
sum += Dfs( j, _cur);
}
if( sum == Sub){ return 0;}
return sum;
}
bool Check( int _s){
Sub = _s;
return Dfs( 0, -1) == 0;
}
int componentValue(vector<int>& AA, vector<vector<int>>& E) {
A = AA;
Graph_init( );
for( auto & i : E){
Graph_addEdge( i[0], i[1]);
Graph_addEdge( i[1], i[0]);
}
int ma = *max_element( A.begin(), A.end());
int sum = accumulate( A.begin(), A.end(), 0);
int ans = 0;
for( int cont = min( int( A.size()), sum / ma); ; --cont){
if( sum % cont == 0){
if( Check( sum / cont)){
return cont - 1;
}
}
}
assert( 0);
return 0;
}
};