// tsukasa_diary's programing contest code template
#include <bits/stdc++.h>
using namespace std;
// define
#define for_(i,a,b) for(int i=a;i<b;++i)
#define for_rev(i,a,b) for(int i=a;i>=b;--i)
#define allof(a) a.begin(),a.end()
#define minit(a,b) memset(a,b,sizeof(a))
#define size_of(a) (int)a.size()
// typedef
typedef long long lint;
typedef double Double;
typedef pair<int, int> pii;
//
typedef vector< int > Array;
typedef vector< Array > Matrix;
typedef vector< Double > DArray;
typedef vector< DArray > DMatrix;
typedef vector< string > SArray;
typedef vector< pii > PArray;
// popcount
inline int POPCNT(int _x) { return __builtin_popcount(_x); }
inline int POPCNT(lint _x) { return __builtin_popcountll(_x); }
// inf
const int iINF = 1L << 30;
const lint lINF = 1LL << 60;
// eps
Double EPS = 1e-9;
// in range
inline bool in_range(int _v, int _mx, int _mi) { return _mi <= _v && _v < _mx; }
inline bool in_range(Double _v, Double _mi, Double _mx) { return -EPS < _v - _mi && _v - _mx < EPS; }
inline bool in_range(int _x, int _y, int _W, int _H) { return 0 <= _x && _x < _W && 0 <= _y && _y < _H; }
// neighbor clockwise
const int DX[4] = {0,1,0,-1}, DY[4] = {-1,0,1,0};
const int DX_[8] = {0,1,1,1,0,-1,-1,-1}, DY_[8] = {-1,-1,0,1,1,1,0,-1};
// variable update
inline void modAdd(int& _a, int _b, int _m) { _a = (_a + _b) % _m; }
inline void modAdd(lint& _a, lint _b, lint _m) { _a = (_a + _b) % _m; }
inline void minUpdate(int& _a, int _b) { _a = min(_a, _b); }
inline void minUpdate(lint& _a, lint _b) { _a = min(_a, _b); }
inline void maxUpdate(int& _a, int _b) { _a = max(_a, _b); }
inline void maxUpdate(lint& _a, lint _b) { _a = max(_a, _b); }

// uniof-find
struct UnionFind {
	vector< int > data;
	UnionFind(int _size) : data(_size, -1) {}
	
	bool unionSet(int _x, int _y) {
		_x = root(_x); _y = root(_y);
		if (_x != _y) {
			if (data[_y] < data[_x]) swap(_x, _y);
			data[_x] += data[_y]; data[_y] = _x;
		}
		return _x != _y;
	}
	
	bool sameSet(int _x, int _y) { return root(_x) == root(_y); }
	
	int root(int _x) { return data[_x] < 0 ? _x : data[_x] = root(data[_x]); }
	
	int size(int _x) { return -data[root(_x)]; }
};

// minimum spanning tree --- with union-find
typedef int cost_type;

struct MS_Edge {
	int from, to; cost_type cost;
	MS_Edge(int _from, int _to, cost_type _cost) : from(_from), to(_to), cost(_cost) {}
};

bool operator < (const MS_Edge& _a, const MS_Edge& _b) { return _a.cost < _b.cost; }

struct MinimumSpanningTree {
	int V;
	vector< MS_Edge > edges;
	
	MinimumSpanningTree(int _n) : V(_n) {}
	
	void add_edge(int _from, int _to, cost_type _cost) {
		edges.push_back(MS_Edge(_from, _to, _cost));
	}
	
	cost_type get_slim(int t) {
		UnionFind uf(V);
		cost_type mn = cost_type(iINF), mx = cost_type();
		int e_size = size_of(edges);
		
		int cnt = 0;
		
		for_(i,t,e_size) {
			MS_Edge e = edges[i];
			if (!uf.sameSet(e.from, e.to)) {
				uf.unionSet(e.from, e.to);
				mn = min(mn, e.cost);
				mx = max(mx, e.cost);
				++cnt;
			}
		}
		
		if (cnt != V - 1) return cost_type(iINF);
		return mx - mn;
	}
	
	cost_type solver() {
		sort(allof(edges));
		
		int e_size = size_of(edges);
		
		cost_type ans = cost_type(iINF);
		for_(i,0,e_size) {
			ans = min(ans, get_slim(i));
		}
		
		if (ans == cost_type(iINF)) ans = -1;
		return ans;
	}
};

int n, m;

void solve() {
	MinimumSpanningTree mst(n);
	
	for_(i,0,m) {
		int u, v, c; cin >> u >> v >> c;
		--u; --v;
		mst.add_edge(u, v, c);
	}
	
	cout << mst.solver() << endl;
}

int main() {
	while (cin >> n >> m, n) {
		solve();
	}
	return 0;
}

Measured memory_bytes: 1328