-
Notifications
You must be signed in to change notification settings - Fork 4
/
CodeForces 1242C - Sum Balance.cpp
145 lines (127 loc) · 4.04 KB
/
CodeForces 1242C - Sum Balance.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//problem link: https://codeforces.com/contest/1242/problem/C
//difficutly: CF 2400
/*solution idea:
First of all we know that each group must eventually have sum equal to (SUM) / k, where SUM is the sum of all elements in all groups
Second we construct an array delta ::= the amount I shoud subtract from or add to each group.
For a certain mask we say it's valid if it can be grouped together (forming a cycle in some order).
note a valid mask must have a delta sum = 0.
We then try constructing all valid masks by walking from some starting node and going through some out-going edge untill we hit the start back.
The time complexity for this is O(k * ni * k).
In the final solution there will be one or more groups connected together each one formming a cycle,
we try to form these groups using DP with time complexity O(3^k) iterating over all masks and their submasks.
The time complexity O(k^2 * ni + 3^k)
The space complexity O(2^k)
*/
#include<bits/stdc++.h>
using namespace std;
const int K = 15;
int k;
long long each;
vector<int> X[K];
vector<int> sz;
vector<long long> delta;
bool can[1 << K];
int dp[1 << K];
map<long long , int> mp;
int solve(int mask){
if(mask == 0)
return 1;
int &ret = dp[mask];
if(ret != -1)
return ret;
ret = 0;
for(int msk = mask; msk; msk = (msk - 1) & mask)
ret |= can[msk] && solve(mask ^ msk);
return ret;
}
vector<int> ans[K];
vector<vector<int>> way[1 << K];
//how can I construct a ginve mask
void process(int mask){
for(auto &v : way[mask])
ans[v[0]] = {v[1], v[2] + 1};
}
void trace(int mask){
if(mask == 0)
return;
for(int msk= mask; msk; msk = (msk - 1) & mask){
if(can[msk] && solve(mask ^ msk)){
process(msk);
trace(mask ^ msk);
return;
}
}
assert(0);
}
int main() {
cin.tie(0);
cin.sync_with_stdio(0);
cin>>k;
sz.resize(k);
delta.resize(k);
long long sum = 0;
for(int i = 0; i < k; i++){
cin>>sz[i];
X[i].resize(sz[i]);
for(int &x : X[i]){
cin>>x;
mp[x] = i;
sum += x;
}
}
if(sum % k){
cout<<"No\n";
return 0;
}
each = sum / k;
for(int i = 0; i < k; i++){
delta[i] = accumulate(X[i].begin(), X[i].end(), 0LL) - each;
}
long long delta_sum[1 << k];
memset(delta_sum, 0LL, sizeof delta_sum);
for(int mask = 0; mask < (1 << k); mask++){
for(int i = 0; i < k; i++){
if(mask & (1 << i)){
delta_sum[mask] += delta[i];
}
}
}
for(int start = 0; start < k; start++){
for(int out : X[start]){
vector<vector<int>> seq;
int node = start;
int mask = 0;
int out_edge = out;
while(true){
mask |= (1 << node);
long long needY = out_edge - delta[node];
if(mp.count(needY) != 0){
seq.push_back({mp[needY], (int)needY, node});
node = mp[needY];
out_edge = needY;
if(node == start){
can[mask] = delta_sum[mask] == 0;
way[mask] = seq;
break;
}else if(mask & (1 << node))
break;
}else break;
}
}
}
memset(dp, -1, sizeof dp);
if(solve((1 << k) - 1)){
cout<<"Yes\n";
trace((1 << k) - 1);
for(auto v : ans){
for(int x : v){
cout<<x<<" ";
}
cout<<"\n";
if(v.size() == 0)
break;
}
}else{
cout<<"No\n";
}
}