#include <fstream>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <bitset>
#define minimum(a,b) \
({ \
typeof(a) _a = a; \
typeof(b) _b = b; \
_a<=_b?_a:_b; \
})
#define MAXN 700
#define INF 0x3f3f3f3f
using namespace std;
typedef unsigned short uint16;
typedef unsigned int uint32;
struct Edge
{
Edge() :
node(0),
cost(0)
{}
Edge(const uint16 n, const short c) :
node(n),
cost(c)
{}
uint16 node;
short cost;
};
typedef vector<vector<Edge> > Graph;
inline void AddSource(Graph& graph, const uint16 n, int** capacity)
{
for (int i=1; i<=n; ++i)
{
graph[i].push_back(Edge(0,0));
graph[0].push_back(Edge(i,0));
capacity[0][i] = 1;
}
}
inline void AddSink(Graph& graph, const uint16 n, const uint16 m, int** capacity)
{
const uint16 dest = n+m+1;
for (int i=1; i<=m; ++i)
{
graph[n+i].push_back(Edge(dest,0));
graph[dest].push_back(Edge(n+i,0));
capacity[n+i][dest] = 1;
}
}
bool BellmanFord(const Graph &graph,
int **capacity,
int **flow,
const uint32 n,
const uint16 s,
int dist[],
int& minFlow
)
{
queue<uint16> Q;
uint16 count[MAXN]={0};
int parent[MAXN]={-1};
bool neg_cycle=false;
bitset<MAXN> inQ;
memset(dist,0x3f,n*sizeof(int));
dist[s]=0;
Q.push(s);
inQ[s]=true;
while(!Q.empty() && !neg_cycle)
{
const uint16 node=Q.front();
Q.pop();
inQ[node]=false;
for (uint32 j=0; j<graph[node].size(); ++j)
{
if (capacity[node][graph[node][j].node] - flow[node][graph[node][j].node] > 0
&& dist[node] + graph[node][j].cost < dist[graph[node][j].node])
{
dist[graph[node][j].node] = dist[node] + graph[node][j].cost;
parent[graph[node][j].node] = node;
if(!inQ[graph[node][j].node])
{
if(count[graph[node][j].node]>n)
{
neg_cycle=true;
}
else
{
Q.push(graph[node][j].node);
inQ[graph[node][j].node]=true;
count[graph[node][j].node]++;
}
}
}
}
}
minFlow = INF;
if (dist[n-1] < INF)
{
for (int i=n-1; i>0; i = parent[i])
{
//cout << i << " ";
minFlow = minimum(minFlow, capacity[parent[i]][i] - flow[parent[i]][i]);
}
//cout << endl;
for (int i=n-1; i>0; i = parent[i])
{
flow[parent[i]][i] += minFlow;
flow[i][parent[i]] -= minFlow;
}
//cout << "dist[n-1] = " << dist[n-1] << endl;
//cout << "minFlow = " << minFlow << endl;
minFlow *= dist[n-1];
//cout << "Current flow is = " << minFlow << endl << endl;
}
return neg_cycle;
}
int MinimumCostMaximumMatching
(
const Graph& graph,
uint32 uGraphSize,
int **capacity,
int **flow,
int dist[]
)
{
int minFlow = 0;
int totalMinFlow = 0;
while (minFlow != INF)
{
totalMinFlow += minFlow;
BellmanFord(graph, capacity, flow, uGraphSize, 0, dist, minFlow);
}
return totalMinFlow;
}
int ConstructSolution
(
const uint16 n,
const uint16 m,
int** capacity,
int** flow,
int** edgeIndices,
/*[out]*/vector<uint16>& vEdges
)
{
int numEdges = 0;
for (uint16 i=1; i<=n; ++i)
{
for (uint16 j=n+1; j<=n+m+1; ++j)
{
if (capacity[i][j] && flow[i][j])
{
numEdges++;
vEdges.push_back(edgeIndices[i][j]);
break;
}
}
}
return numEdges;
}
int main()
{
uint16 n,m;
uint32 E;
int **capacity, **flow, **edgeIndices, *dist;
fstream fin("cmcm.in", fstream::in);
fstream fout("cmcm.out", fstream::out);
Graph graph;
vector<uint16> vEdges;
fin >> n >> m >> E;
//cout << n << " " << m << " " << E << endl;
const uint16 uGraphSize = n+m+2;
graph.resize(uGraphSize);
dist = new int[uGraphSize];
capacity = new int*[uGraphSize];
flow = new int*[uGraphSize];
edgeIndices = new int*[uGraphSize];
for (int i=0; i<uGraphSize; ++i)
{
capacity[i] = new int[uGraphSize];
memset(capacity[i], 0, sizeof(int)*uGraphSize);
flow[i] = new int[uGraphSize];
memset(flow[i], 0, sizeof(int)*uGraphSize);
edgeIndices[i] = new int[uGraphSize];
memset(edgeIndices[i], 0, sizeof(int)*uGraphSize);
}
// read and build graph
for (uint32 i=0; i<E; ++i)
{
uint16 x, y;
short c;
fin >> x >> y >> c;
//cout << x << " " << y << " " << c << endl;
graph[x].push_back(Edge(n+y,c));
graph[n+y].push_back(Edge(x,-c));
capacity[x][n+y] = 1;
edgeIndices[x][n+y] = i;
}
AddSource(graph, n, capacity);
AddSink(graph, n, m, capacity);
// perform minim cost matching
int totalMinFlow = MinimumCostMaximumMatching(graph, uGraphSize, capacity, flow, dist);
//cout << totalMinFlow << endl;
int numEdges = ConstructSolution(n, m, capacity, flow, edgeIndices, vEdges);
fout << numEdges << " " << totalMinFlow << "\n";
for (uint16 i=0; i<numEdges; ++i)
fout << vEdges[i]+1 << " ";
fout << "\n";
fin.close();
fout.close();
return 0;
}