#include <stdio.h>
#include <vector>
#include <bitset>
#include <set>
#include <algorithm>
#include <cassert>
using namespace std;
#define maxN 610
#define oo 1000000
#define X 20000
#define maxM 50100
struct edge {
int who, cost, chosed;
};
bitset <maxN> RTS;
bitset <maxM> visible, viz;
vector <int> RS, RT, Solv;
vector <edge> G[maxN], V[maxN];
set <int> Z, T_Z, Z_I_T;
int N, M, E, pred[maxN], Q[maxN], st, dr, y[maxN], Cost[maxM], Sol_cuplaj;
bool Z_RT;
void print () {
int i, j;
/*
printf("*************************************************************\n");
for (i = 1; i <= N + M; ++ i) {
for (j = 0; j < (int) G[i].size(); ++ j)
printf("[%d %d %d]", G[i][j].who, G[i][j].cost, G[i][j].chosed);
puts("");
}*/
//printf("_________________________________\n");
for (i = N + 1; i <= N + M; ++ i)
for (j = 0; j < (int) G[i].size(); ++ j)
if (G[i][j].chosed) {
Solv.push_back(G[i][j].cost);
}
//printf("*************************************************************\n");
}
void compute_rs () {
visible.reset(); RS.clear();
for (int i = N + 1; i <= N + M; ++ i)
for (int j = 0; j < (int) G[i].size(); ++ j)
if (G[i][j].chosed)
visible[G[i][j].who] = 1;
for (int i = 1; i <= N; ++ i)
if (! visible[i])
RS.push_back(i);
}
void compute_rt () {
visible.reset(); RT.clear(); Z_RT = 0;
RTS.reset();
for (int i = N + 1; i <= N + M; ++ i)
for (int j = 0; j < (int) G[i].size(); ++ j)
if (G[i][j].chosed)
visible[i] = 1;
for (int i = N + 1; i <= N + M; ++ i)
if (!visible[i]) {
RT.push_back(i);
RTS[i] = 1;
}
}
void bf () {
int now, ok = 1;
viz.reset(); Z.clear();
for (int i = 1; i <= N + M; ++ i) {
viz[i] = 0;
pred[i] = i;
}
st = dr = 0;
for (int i = 0; i < (int) RS.size(); ++ i) {
Q[dr ++] = RS[i];
viz[RS[i]] = 1;
}
for (; st < dr && ok;) {
now = Q[st ++];
for (int j = 0; j < (int) G[now].size() && ok; ++ j) {
if (G[now][j].chosed && !viz[G[now][j].who]) {
// printf("now = %d, G[now][j].who = %d G[now][j].chosed = %d\n", now, G[now][j].who, G[now][j].chosed);
viz[G[now][j].who] = 1;
pred[G[now][j].who] = now;
Q[dr ++] = G[now][j].who;
if (RTS[G[now][j].who] == 1)
ok = false;
}
}
}
for (int i = 1; i <= N + M; ++ i)
if (viz[i]) {
// printf("i = %d ", i);
Z.insert(i);
}
}
bool matching () {
int i, next, now, c2, c3, c1;
compute_rs();
compute_rt();
bf();
T_Z.clear(); Z_I_T.clear();
for (i = 0; i < (int) RT.size(); ++ i)
Z_RT |= (Z.find(RT[i]) != Z.end());
for (i = N + 1; i <= N + M; ++ i)
T_Z.insert(i);
// fprintf(stderr, "%d\n", Sol_cuplaj);
for (set <int> :: iterator it = Z.begin(); it != Z.end(); ++ it)
T_Z.erase(*it);
for (i = N + 1; i <= N + M; ++ i)
if (Z.find(i) != Z.end())
Z_I_T.insert(i);
/*
printf("RS: ");
for (i = 0; i < (int) RS.size(); ++ i)
printf("%d ", RS[i]);
puts("");
printf("RT: ");
for (int j = 0; j < (int) RT.size(); ++ j)
printf("%d ", RT[j]);
puts("");
printf("Z: ");
for (set <int> :: iterator it = Z.begin(); it != Z.end(); ++ it)
printf("%d ", *it);
puts("");
printf("T_Z: ");
for (set <int> :: iterator it = T_Z.begin(); it != T_Z.end(); ++ it)
printf("%d ", *it);
puts("");
printf("Z_I_T: ");
for (set <int> :: iterator it = Z_I_T.begin(); it != Z_I_T.end(); ++ it)
printf("%d ", *it);
puts("");
printf("Z_RT : %d\n", (int) Z_RT);
printf("G: ");
for (i = 1; i <= N; ++ i)
for (int j = 0; j < (int) G[i].size(); ++ j)
if (G[i][j].chosed)
printf("%d -> %d ", i, G[i][j].who);
else
printf("%d <- %d ", i, G[i][j].who);
printf("\n");
*/
if (Z_RT) {
// fprintf(stderr, "OK");
for (; dr && Q[dr - 1] <= N; -- dr);
assert(dr);
for (now = Q[dr - 1]; pred[now] != now; now = pred[now]) {
next = pred[now];
for (i = 0; i < (int) G[now].size(); ++ i)
if (G[now][i].who == next) {
if (now <= N)
Sol_cuplaj --;
else
Sol_cuplaj ++;
G[now][i].chosed ^= 1;
}
for (i = 0; i < (int) G[next].size(); ++ i)
if (G[next][i].who == now) {
// if (G[next][i].chosed)
// Sol_cuplaj --;
// else
// Sol_cuplaj ++;
G[next][i].chosed ^= 1;
}
}
} else {
int Sol = oo;
c1 = 0; c2 = 0; c3 = 0;
for (now = 1; now <= N; ++ now) {
if (Z.find(now) == Z.end()) continue;
for (int j = 0; j < (int) V[now].size(); ++ j)
if (T_Z.find(V[now][j].who) != T_Z.end() && ! V[now][j].chosed) {
if (Cost[V[now][j].cost] - y[now] - y[V[now][j].who] < Sol) {
Sol = Cost[V[now][j].cost] - y[now] - y[V[now][j].who];
c1 = now;
c2 = V[now][j].who;
c3 = V[now][j].cost;
}
}
}
// printf("c1 = %d c2 = %d delta = %d\n", c1, c2, Sol);
// if (Sol == oo) return 0;
for (i = 1; i <= N; ++ i)
if (Z.find(i) != Z.end())
y[i] += Sol;
for (i = N + 1; i <= N + M; ++ i)
if (Z.find(i) != Z.end())
y[i] -= Sol;
G[c1].push_back((edge) {c2, c3, 1});
G[c2].push_back((edge) {c1, c3, 0});
for (i = 0; i < (int) V[c2].size(); ++ i)
if (V[c2][i].who == c1)
V[c2][i].chosed = 1;
for (i = 0; i < (int) V[c1].size(); ++ i)
if (V[c1][i].who == c2)
V[c1][i].chosed = 1;
}
// print();
/*
printf("G: ");
for (i = 1; i <= N; ++ i)
for (int j = 0; j < (int) G[i].size(); ++ j)
if (G[i][j].chosed)
printf("%d -> %d ", i, G[i][j].who);
else
printf("%d <- %d ", i, G[i][j].who);
printf("\n");
fprintf(stdout, "Sol = %d\n", Sol_cuplaj);
for (i = 1; i <= N; ++ i)
fprintf(stdout, "%d ", y[i]);
puts("");
for (i = 1; i <= M; ++ i)
fprintf(stdout, "%d ", y[i + N]);
puts("");
puts("");*/
return 1;
}
int main () {
int a, b, c, i;
freopen("cmcm.in", "r", stdin);
freopen("cmcm.out", "w", stdout);
scanf("%d%d%d", &N, &M, &E);
for (i = 1; i <= E; ++ i) {
scanf("%d%d%d", &a, &b, &Cost[i]);
Cost[i] += X;
V[a].push_back((edge) {b + N, i, 0});
}
for (i = 0; matching () && Sol_cuplaj < min(N, M); ++ i);
print();
sort(Solv.begin(), Solv.end());
int sol_cost = 0;
for (i = 0; i < (int) Solv.size(); ++ i)
sol_cost += Cost[Solv[i]] - X;
printf("%d %d\n", Solv.size(), sol_cost);
for (i = 0; i < (int) Solv.size(); ++ i)
printf("%d ", Solv[i]);
}