// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

const int maxn = 50010;

struct node 

{

      int u,v,w;

      bool used,mark,del;

      node(int x = 0,int y = 0,int z = 0) 

	  {

        u = x;

        v = y;

        w = z;

        mark = del = used = false;

     }

     bool operator<(const node &tmp) const 

	 {

         return w < tmp.w;

     }

 }e[maxn];

 int uf[maxn],n,m,cnt;

 bool flag[maxn];

 int find(int x) {

     return uf[x] = uf[x] == x?uf[x]:find(uf[x]);

 }

 int kruskal(bool &Unique,bool first) {

     int ans = cnt = 0;

     for(int i = 0; i <= n; ++i) uf[i] = i;

     for(int i = 0; i < m; ++i) {

        if(!first && e[i].del) continue;

        int fx = find(e[i].u);

        int fy = find(e[i].v);

       if(fx != fy)

	   {

    	   	uf[fx] = fy;

            ans += e[i].w;

            if(first) 

			{

            e[i].used = true;

            if(e[i].mark) Unique = false;

            }

            if(++cnt == n-1) return ans;

	   }

     }

     return ans;

 }

 int main() {

     int u,v,w;

    // freopen("data.in","r",stdin); 

     while(~scanf("%d %d",&n,&m)) {

         for(int i = 0; i < m; ++i) {

             scanf("%d %d %d",&u,&v,&w);

             e[i] = node(u,v,w);

         }

         memset(flag,false,sizeof(flag));

         sort(e,e+m);

         for(int i = 1; i < m; ++i)

             if(e[i].w == e[i-1].w) e[i].mark = e[i-1].mark = true;

         bool Unique = true;

         int MST = kruskal(Unique,1);

         if(Unique) printf("%d %d\n",cnt,MST);

         else {

             int res1 = 0,res2 = 0;

             for(int i = 0; i < m; ++i) {

                 if(e[i].used && e[i].mark) {

                     e[i].del = true;

                     int mst = kruskal(Unique,0);

                     if(mst == MST && cnt == n-1) flag[i] = true;

                     e[i].del = false;

                 }

               if(e[i].used && !flag[i]) {

                     res1++;

                     res2 += e[i].w;

                 }

             }

             printf("%d %d\n",res1,res2);

        }

     }

     return 0;

 }

// Faster C++ solution for the same problem (measured speedup: 1.9149678740938387x):
/* BISMILLAHIR RAHMANIR RAHIM */

#include <bits/stdc++.h>

//#include <ext/pb_ds/assoc_container.hpp>

//#include <ext/pb_ds/tree_policy.hpp>



using namespace std;

//using namespace __gnu_pbds;



#define FasterIO ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0)



#define F first

#define S second

#define pb push_back

#define pk pop_back

#define PQ priority_queue



typedef long long ll;

typedef queue<int> qi;

typedef vector<int> vi;

typedef vector<ll> vl;

typedef pair<int, int> pii;

typedef pair<int, pii> piii;

typedef vector<pii> vii;



//typedef tree<

//  int, null_type,

//  less<int>, rb_tree_tag,

//  tree_order_statistics_node_update > ordered_set;



#define sc scanf

#define pf printf

#define sc1(x) scanf("%d", &x)

#define sc2(x, y) scanf("%d %d", &x, &y)

#define sc3(x, y, z) scanf("%d %d %d", &x, &y, &z)

#define scl1(x) scanf("%lld", &x)

#define scl2(x, y) scanf("%lld %lld", &x, &y)

#define scl3(x, y, z) scanf("%lld %lld %lld", &x, &y, &z)

#define pf1(x) printf("%d", x)

#define pf2(x, y) printf("%d %d", x, y)

#define pf3(x, y, z) printf("%d %d %d", x, y, z)

#define pfl1(x) printf("%lld", x)

#define pfl2(x, y) printf("%lld %lld", x, y)

#define pfl3(x, y, z) printf("%lld %lld %lld", x, y, z)

#define NL printf("\n")

#define FK printf(" ")

#define bug printf("ok :: ")



#define all(x) x.begin(), x.end()

#define rall(x) x.rbegin(), x.rend()

#define MEM(a, x) memset(a, x, sizeof(a))

#define MEMV(a, n, x) for(int i = 0; i <= n; a[i] = x, i++)



#define Fr(i, a, b, x) for(int i = a; i <= b; i += x)

#define Rv(i, a, b, x) for(int i = a; i >= b; i -= x)

#define seg_mid_L_R int mid = l + (r - l) / 2, lft = nd << 1, rgt = lft | 1



/* 6291469, 12582917, 402653189, 1610612741 */



#define read freopen("INPUT.txt", "r", stdin)

#define write freopen("OUTPUT.txt", "w", stdout)



#define inf 1e14

#define MOD 1000000007

#define MX_N 50005

#define LG 11

/*---------------------------------------------------------------------------------*/

int n, m;

vector<piii> E;



int P[MX_N];

vii used;



int Root( int u ) {

  while( u != P[u] ) {

    P[u] = P[P[u]];

    u = P[u];

  }

  return P[u];

}



ll krushkal_MST( int bad, int ok ) {

  Fr(i, 0, n, 1) P[i] = i;

  ll cost = 0, cnt = 0;

  Fr(i, 0, m - 1, 1) {

    if( i == bad ) continue;

    piii e = E[i];

    int u = e.S.F;

    int v = e.S.S;

    if( Root(u) != Root(v) ) {

      u = Root(u);

      v = Root(v);

      P[u] = P[v];

      cost += e.F, cnt++;

      if( ok ) used.pb({i, e.F});

    }

  }

  return (cnt == n - 1) ? cost : inf;

}



int main() {

  sc2(n, m);

  Fr(i, 1, m, 1) {

    int u, v, w;

    sc3(u, v, w);

    E.pb({w, {u, v}});

  }

  sort(E.begin(), E.end());



  ll C = krushkal_MST( -1, 1 ), res = 0LL, cnt = 0LL;



  for(auto& b : used) {

    ll tC = krushkal_MST( b.F, 0 );

    if( C != tC ) {

      res += b.S, cnt++;

    }

  }



  pfl2(cnt, res), NL;

  return 0;

}