const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    const lines = [];
    const N = parseInt(await readline());
    for (let i = 0; i < N; i++) {
        const line = (await readline()).trim().split(" ").map(Number);
        lines.push(line);
    }

    // 邻接表
    const adj = new Map();
    // 所有节点集合
    const nodes = new Set();
    // 节点入度存储
    const inDegree = new Map();

    // 处理输入的边和节点
    for (let i = 0; i < N; i++) {
        const [u, v, p] = lines[i];
        // 没有处理过就初始化
        if (!adj.has(u)) adj.set(u, []);
        adj.get(u).push({ v, p });
        // 更新节点集合
        nodes.add(u);
        nodes.add(v);
        // 更新入度表
        if (!inDegree.has(v)) inDegree.set(v, 0);
        inDegree.set(v, inDegree.get(v) + 1);
        // 起点的入度如果不存在也初始化为 0
        if (!inDegree.has(u)) inDegree.set(u, 0);
    }

    // 处理无节点的特殊情况
    if (nodes.size === 0) {
        console.log("0 0");
        return;
    }

    // 拓扑排序检测环,并记录拓扑序列
    const inDegreeCopy = new Map(inDegree);
    // 拓扑序列
    const topoOrder = [];
    // 入度为0的队列
    const queue = [];

    for (const node of nodes) {
        if (inDegreeCopy.get(node) === 0) {
            queue.push(node);
        }
    }

    // 拓扑序列的节点个数
    let count = 0;
    while (queue.length > 0) {
        const u = queue.shift();
        topoOrder.push(u);
        count++;
        // 遍历u的领居
        if (adj.has(u)) {
            for (const { v } of adj.get(u)) {
                inDegreeCopy.set(v, inDegreeCopy.get(v) - 1);
                if (inDegreeCopy.get(v) === 0) {
                    queue.push(v);
                }
            }
        }
    }

    // 存在环的情况
    if (count !== nodes.size) {
        console.log(-1);
        return;
    }

    // 到达节点时的最大利润
    const dp = new Map();
    // 最大利润下的节点数
    const cnt = new Map();
    for (const node of nodes) {
        dp.set(node, -Infinity);
        cnt.set(node, 0);
    }

    // 入度为0的节点初始化
    for (const node of nodes) {
        if (inDegree.get(node) === 0) {
            dp.set(node, 0);
            cnt.set(node, 1);
        }
    }

    // 按照拓扑序列更新dp和cnt
    for (const u of topoOrder) {
        if (adj.has(u)) {
            // 遍历邻居
            for (const { v, p } of adj.get(u)) {
                const newProfit = dp.get(u) + p;
                const newCount = cnt.get(u) + 1;
                if (newProfit > dp.get(v)) {
                    dp.set(v, newProfit);
                    cnt.set(v, newCount);
                } else if (newProfit === dp.get(v)) {
                    // 利润相同,根据个数
                    if (newCount > cnt.get(v)) {
                        cnt.set(v, newCount);
                    }
                }
            }
        }
    }

    // 寻找最大利润和对应的最长节点数
    let maxProfit = -Infinity;
    let maxCount = 0;

    for (const node of topoOrder) {
        const currentProfit = dp.get(node);
        const currentCount = cnt.get(node);
        if (currentProfit > maxProfit) {
            maxProfit = currentProfit;
            maxCount = currentCount;
        } else if (currentCount === maxProfit) {
            if (currentCount > maxCount) {
                maxCount = currentCount;
            }
        }
    }

    console.log(`${maxProfit} ${maxCount}`);
}()