#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;
pair<int, int> edges[300];
int c[300], n;
// depend on the underlying matroid M1
// X: vector 0-1
vector<int> get_matroid_1_circuit(int id, vector<int> &X) {
for(int elem = 0; elem < n; elem++) if(X[elem] && edges[id].first == edges[elem].first) {
return {elem};
}
return {};
}
// depend on the underlying matroid M2
vector<int> get_matroid_2_circuit(int id, vector<int> &X) {
for(int elem = 0; elem < n; elem++) if(X[elem] && edges[id].second == edges[elem].second) {
return {elem};
}
return {};
}
// modified to work in O(E) for sets of large edges
pair<vector<int>, vector<int>> dijkstra(vector<vector<pair<int, int>>> &graph) {
vector<int> reached, parent, dist;
parent.resize(n + 2, -1);
reached.resize(n + 2, 0);
dist.resize(n + 2, 1'000'000'000);
dist[n] = 0;
parent[n] = n;
while(true) {
int m = n + 1;
for(int i = 0; i < n + 2; i++) if(!reached[i] && dist[i] < dist[m] && parent[i] != -1) m = i;
// m == n + 1 if and only if dist[t] = infinity, t is not reachable or shortest s-t path found
if(m == n + 1) break;
for(auto adj: graph[m]) if(dist[adj.first] > dist[m] + adj.second) {
dist[adj.first] = dist[m] + adj.second;
parent[adj.first] = m;
}
reached[m] = 1;
}
return {parent, dist};
}
vector<int> matroid_intersection() {
// X is a bitmask vector
vector<int> w1, w2, X;
vector<vector<pair<int, int>>> exchange_graph;
int s = n, t = n + 1;
w1.resize(n);
w2.resize(n);
X.resize(n);
exchange_graph.resize(n + 2);
for(int i = 0; i < n; i++) {
w1[i] = c[i];
w2[i] = 0;
X[i] = 0;
}
while(true) {
//constructing exchange_graph
for(int i = 0; i < n + 2; i++) exchange_graph[i].clear();
for(int y = 0; y < n; y++) if(!X[y]) {
vector<int> adj_m1 = get_matroid_1_circuit(y, X);
if(adj_m1.empty()) {
exchange_graph[s].push_back({y, w1[y]});
}
else {
for(auto x: adj_m1) exchange_graph[x].push_back({y, w1[y] - w1[x]});
}
vector<int> adj_m2 = get_matroid_2_circuit(y, X);
if(adj_m2.empty()) {
exchange_graph[y].push_back({t, w2[y]});
}
else {
for(auto x: adj_m2) exchange_graph[y].push_back({x, w2[y] - w2[x]});
}
}
auto [parent, dist] = dijkstra(exchange_graph);
// t is not reachable
if(parent[t] == -1) break;
//modify the weight function
for(int i = 0; i < n; i++) if(dist[i] <= dist[s]) {
w1[i] = w1[i] - dist[s] + dist[i];
w2[i] = w2[i] + dist[s] - dist[i];
}
int path = t;
//augument X along the shortest path with the shortest length
while(path != s) {
path = parent[path];
if(path != s) X[path] ^= 1;
}
}
return X;
}
int main() {
scanf("%d", &n);
for(int i = 0; i < n; i++) scanf("%d %d %d", &edges[i].first, &edges[i].second, &c[i]);
vector<int> best = matroid_intersection();
int sum = 0;
for(int id = 0; id < n; id++) if(best[id]) sum += c[id];
printf("%d\n", sum);
for(int id = 0; id < n; id++) if(best[id]) printf("%d %d\n", edges[id].first, edges[id].second);
}
/*
8
1 1 0
1 2 0
2 1 0
2 4 2
3 2 1
3 3 0
4 3 0
4 4 9
*/
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxxdWV1ZT4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnBhaXI8aW50LCBpbnQ+IGVkZ2VzWzMwMF07CmludCBjWzMwMF0sIG47CgovLyBkZXBlbmQgb24gdGhlIHVuZGVybHlpbmcgbWF0cm9pZCBNMSAKLy8gWDogdmVjdG9yIDAtMQp2ZWN0b3I8aW50PiBnZXRfbWF0cm9pZF8xX2NpcmN1aXQoaW50IGlkLCB2ZWN0b3I8aW50PiAmWCkgewogICAgZm9yKGludCBlbGVtID0gMDsgZWxlbSA8IG47IGVsZW0rKykgaWYoWFtlbGVtXSAmJiBlZGdlc1tpZF0uZmlyc3QgPT0gZWRnZXNbZWxlbV0uZmlyc3QpIHsKICAgICAgICByZXR1cm4ge2VsZW19OwogICAgfQogICAgcmV0dXJuIHt9Owp9Ci8vIGRlcGVuZCBvbiB0aGUgdW5kZXJseWluZyBtYXRyb2lkIE0yCnZlY3RvcjxpbnQ+IGdldF9tYXRyb2lkXzJfY2lyY3VpdChpbnQgaWQsIHZlY3RvcjxpbnQ+ICZYKSB7CiAgICBmb3IoaW50IGVsZW0gPSAwOyBlbGVtIDwgbjsgZWxlbSsrKSBpZihYW2VsZW1dICYmIGVkZ2VzW2lkXS5zZWNvbmQgPT0gZWRnZXNbZWxlbV0uc2Vjb25kKSB7CiAgICAgICAgcmV0dXJuIHtlbGVtfTsKICAgIH0KICAgIHJldHVybiB7fTsKfQovLyBtb2RpZmllZCB0byB3b3JrIGluIE8oRSkgZm9yIHNldHMgb2YgbGFyZ2UgZWRnZXMKcGFpcjx2ZWN0b3I8aW50PiwgdmVjdG9yPGludD4+IGRpamtzdHJhKHZlY3Rvcjx2ZWN0b3I8cGFpcjxpbnQsIGludD4+PiAmZ3JhcGgpIHsKICAgIHZlY3RvcjxpbnQ+IHJlYWNoZWQsIHBhcmVudCwgZGlzdDsKICAgIHBhcmVudC5yZXNpemUobiArIDIsIC0xKTsKICAgIHJlYWNoZWQucmVzaXplKG4gKyAyLCAwKTsKICAgIGRpc3QucmVzaXplKG4gKyAyLCAxJzAwMCcwMDAnMDAwKTsgCiAgICBkaXN0W25dID0gMDsKICAgIHBhcmVudFtuXSA9IG47CiAgICB3aGlsZSh0cnVlKSB7CiAgICAgICAgaW50IG0gPSBuICsgMTsKICAgICAgICBmb3IoaW50IGkgPSAwOyBpIDwgbiArIDI7IGkrKykgaWYoIXJlYWNoZWRbaV0gJiYgZGlzdFtpXSA8IGRpc3RbbV0gJiYgcGFyZW50W2ldICE9IC0xKSBtID0gaTsKICAgICAgICAvLyBtID09IG4gKyAxIGlmIGFuZCBvbmx5IGlmIGRpc3RbdF0gPSBpbmZpbml0eSwgdCBpcyBub3QgcmVhY2hhYmxlIG9yIHNob3J0ZXN0IHMtdCBwYXRoIGZvdW5kCiAgICAgICAgaWYobSA9PSBuICsgMSkgYnJlYWs7CiAgICAgICAgZm9yKGF1dG8gYWRqOiBncmFwaFttXSkgaWYoZGlzdFthZGouZmlyc3RdID4gZGlzdFttXSArIGFkai5zZWNvbmQpIHsKICAgICAgICAgICAgZGlzdFthZGouZmlyc3RdID0gZGlzdFttXSArIGFkai5zZWNvbmQ7CiAgICAgICAgICAgIHBhcmVudFthZGouZmlyc3RdID0gbTsKICAgICAgICB9CiAgICAgICAgcmVhY2hlZFttXSA9IDE7CiAgICB9CiAgICByZXR1cm4ge3BhcmVudCwgZGlzdH07Cn0KdmVjdG9yPGludD4gbWF0cm9pZF9pbnRlcnNlY3Rpb24oKSB7CiAgICAvLyBYIGlzIGEgYml0bWFzayB2ZWN0b3IKICAgIHZlY3RvcjxpbnQ+IHcxLCB3MiwgWDsKICAgIHZlY3Rvcjx2ZWN0b3I8cGFpcjxpbnQsIGludD4+PiBleGNoYW5nZV9ncmFwaDsKICAgIGludCBzID0gbiwgdCA9IG4gKyAxOwogICAgdzEucmVzaXplKG4pOwogICAgdzIucmVzaXplKG4pOwogICAgWC5yZXNpemUobik7CiAgICBleGNoYW5nZV9ncmFwaC5yZXNpemUobiArIDIpOwogICAgZm9yKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIHcxW2ldID0gY1tpXTsKICAgICAgICB3MltpXSA9IDA7CiAgICAgICAgWFtpXSA9IDA7CiAgICB9CiAgICB3aGlsZSh0cnVlKSB7CiAgICAgICAgLy9jb25zdHJ1Y3RpbmcgZXhjaGFuZ2VfZ3JhcGgKICAgICAgICBmb3IoaW50IGkgPSAwOyBpIDwgbiArIDI7IGkrKykgZXhjaGFuZ2VfZ3JhcGhbaV0uY2xlYXIoKTsKICAgICAgICBmb3IoaW50IHkgPSAwOyB5IDwgbjsgeSsrKSBpZighWFt5XSkgewogICAgICAgICAgICB2ZWN0b3I8aW50PiBhZGpfbTEgPSBnZXRfbWF0cm9pZF8xX2NpcmN1aXQoeSwgWCk7CiAgICAgICAgICAgIGlmKGFkal9tMS5lbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBleGNoYW5nZV9ncmFwaFtzXS5wdXNoX2JhY2soe3ksIHcxW3ldfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBmb3IoYXV0byB4OiBhZGpfbTEpIGV4Y2hhbmdlX2dyYXBoW3hdLnB1c2hfYmFjayh7eSwgdzFbeV0gLSB3MVt4XX0pOwogICAgICAgICAgICB9IAogICAgICAgICAgICB2ZWN0b3I8aW50PiBhZGpfbTIgPSBnZXRfbWF0cm9pZF8yX2NpcmN1aXQoeSwgWCk7CiAgICAgICAgICAgIGlmKGFkal9tMi5lbXB0eSgpKSB7CiAgICAgICAgICAgICAgICBleGNoYW5nZV9ncmFwaFt5XS5wdXNoX2JhY2soe3QsIHcyW3ldfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBmb3IoYXV0byB4OiBhZGpfbTIpIGV4Y2hhbmdlX2dyYXBoW3ldLnB1c2hfYmFjayh7eCwgdzJbeV0gLSB3Mlt4XX0pOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGF1dG8gW3BhcmVudCwgZGlzdF0gPSBkaWprc3RyYShleGNoYW5nZV9ncmFwaCk7CiAgICAgICAgLy8gdCBpcyBub3QgcmVhY2hhYmxlCiAgICAgICAgaWYocGFyZW50W3RdID09IC0xKSBicmVhazsKICAgICAgICAvL21vZGlmeSB0aGUgd2VpZ2h0IGZ1bmN0aW9uCiAgICAgICAgZm9yKGludCBpID0gMDsgaSA8IG47IGkrKykgIGlmKGRpc3RbaV0gPD0gZGlzdFtzXSkgewogICAgICAgICAgICB3MVtpXSA9IHcxW2ldIC0gZGlzdFtzXSArIGRpc3RbaV07CiAgICAgICAgICAgIHcyW2ldID0gdzJbaV0gKyBkaXN0W3NdIC0gZGlzdFtpXTsKICAgICAgICB9IAogICAgICAgIGludCBwYXRoID0gdDsKICAgICAgICAvL2F1Z3VtZW50IFggYWxvbmcgdGhlIHNob3J0ZXN0IHBhdGggd2l0aCB0aGUgc2hvcnRlc3QgbGVuZ3RoCiAgICAgICAgd2hpbGUocGF0aCAhPSBzKSB7CiAgICAgICAgICAgIHBhdGggPSBwYXJlbnRbcGF0aF07CiAgICAgICAgICAgIGlmKHBhdGggIT0gcykgWFtwYXRoXSBePSAxOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBYOwp9CgppbnQgbWFpbigpIHsKICAgIHNjYW5mKCIlZCIsICZuKTsKICAgIGZvcihpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHNjYW5mKCIlZCAlZCAlZCIsICZlZGdlc1tpXS5maXJzdCwgJmVkZ2VzW2ldLnNlY29uZCwgJmNbaV0pOwogICAgdmVjdG9yPGludD4gYmVzdCA9IG1hdHJvaWRfaW50ZXJzZWN0aW9uKCk7CiAgICBpbnQgc3VtID0gMDsKICAgIGZvcihpbnQgaWQgPSAwOyBpZCA8IG47IGlkKyspIGlmKGJlc3RbaWRdKSBzdW0gKz0gY1tpZF07CiAgICBwcmludGYoIiVkXG4iLCBzdW0pOwogICAgZm9yKGludCBpZCA9IDA7IGlkIDwgbjsgaWQrKykgaWYoYmVzdFtpZF0pIHByaW50ZigiJWQgJWRcbiIsIGVkZ2VzW2lkXS5maXJzdCwgZWRnZXNbaWRdLnNlY29uZCk7Cn0KLyoKOAoxIDEgMAoxIDIgMAoyIDEgMAoyIDQgMgozIDIgMQozIDMgMAo0IDMgMAo0IDQgOQoqLw==