#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		int count = 0;
		while (now <= q) {
			cout++;
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			if (count >= 1000) {
				printf("%d\n", index);
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			} else {
				last += now;
				if (last > q) {
					last = q;
				}
			}
			long long aaa = 1;
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		while (now <= q) {
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			}
			if (last > q) {
				last = q;
			}
			ret += _data[index] * (last - now + 1) % MOD + v[index] * (last - now) * (last - now + 1) / 2;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		int count = 0;
		while (now <= q) {
			count++;
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			if (count >= 1000) {
				printf("%d\n", index);
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			} else {
				last += now;
				if (last > q) {
					last = q;
				}
			}
			long long aaa = 1;
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		int count = 0;
		while (now <= q) {
			count++;
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (count >= 1000) {
				printf("%d\n", last);
			}
			if (last == -1) {
				last = q;
			} else {
				last += now;
				if (last > q) {
					last = q;
				}
			}
			long long aaa = 1;
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now + 1) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		while (now <= q) {
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			int last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				int t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			}
			if (last > q) {
				last = q;
			}
			ret += _data[index] * (last - now + 1) % MOD + v[index] * (last - now) * (last - now + 1) / 2;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		int count = 0;
		while (now <= q) {
			count++;
			if (count >= 1000) {
				printf("%d\n", count);
			}
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			}
			if (last > q) {
				last = q;
			}
			long long aaa = 1;
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		int count = 0;
		while (now <= q) {
			count++;
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (count >= 1000) {
				printf("%d\n", last);
			}
			if (last == -1) {
				last = q;
			} else {
				last += now;
				if (last > q) {
					last = q;
				}
			}
			long long aaa = 1;
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;

	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		if (n == 2000 && m == 1999 && q == 1000000000) {
			if (w != 999999) {
				printf("%d %d %d\n", x, y, w);
			}
		}
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		int count = 0;
		while (now <= q) {
			count++;
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			} else {
				last += now;
				if (last > q) {
					last = q;
				}
			}
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now + 1) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		while (now <= q) {
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			int last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				int t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			}
			if (last > q) {
				last = q;
			}
			ret += _data[index] * (last - now + 1) + v[index] * (last - now) * (last - now + 1) / 2;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		int count = 0;
		while (now <= q) {
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			} else {
				last += now;
				if (last > q) {
					last = q;
				}
			}
			long long aaa = 1;
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;

	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		if (n == 2000 && m == 1999 && q == 1000000000) {
			if (w != 999999 && w != 1) {
				printf("%d %d %d\n", x, y, w);
			}
		}
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		int count = 0;
		while (now <= q) {
			count++;
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			} else {
				last += now;
				if (last > q) {
					last = q;
				}
			}
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now + 1) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;

	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i <= n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		// printf("%lld\n", _data[1]);
		// printf("%lld\n", _data[2000]);
		int count = 0;
		while (now <= q) {
			count++;
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				// if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
				// 	t++;
				// }
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			} else {
				last += now;
				if (last > q) {
					last = q;
				}
			}
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			// printf("%lld %lld %lld\n", _data[1], _data[2000], last);
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now + 1) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		while (now <= q) {
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			}
			if (last > q) {
				last = q;
			}
			long long aaa = 1;
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;
	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i < n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		while (now <= q) {
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			}
			if (last > q) {
				last = q;
			}
			long long aaa = 1;
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

long long _data[2010];
long long _next[2010];
vector<pair<int, int>> edges[2010];
long long v[2010];
const int MOD = 1000000007;

void getNext(int n) {
	memset(_next, -1, sizeof(_next));
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		for (int j = 0;j < edges[i].size();j++) {
			int y = edges[i][j].first;
			int w = edges[i][j].second;
			if (_next[y] == -1 || _next[y] < _data[i] + w) {
				_next[y] = _data[i] + w;
			}
		}
	}
}

long long getMax(int n) {
	long long ret = -1;
	for (int i = 1;i <= n;i++) {
		if (_data[i] == -1) {
			continue;
		}
		if (ret == -1 || ret < _data[i]) {
			ret = _data[i];
		}
	}
	return ret;
}

int main() {
	int n, m, q;
	scanf("%d%d%d", &n, &m, &q);
	memset(_data, -1, sizeof(_data));
	_data[1] = 0;

	for (int i = 0;i < m;i++) {
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		edges[x].push_back(make_pair(y, w));
		edges[y].push_back(make_pair(x, w));
	}
	long long ret = 0;
	int i = 0;
	for (;i < 2 * n && i < q;i++) {
		getNext(n);
		memcpy(_data, _next, sizeof(_data));
		ret += getMax(n);
		ret %= MOD;
	}
	int now = 2 * n + 1;
	if (i == q) {
		printf("%d\n", ret);
	} else {
		for (int i = 1;i <= n;i++) {
			v[i] = -1;
			for (int j = 0;j < edges[i].size();j++) {
				if (v[i] == -1 || v[i] < edges[i][j].second) {
					v[i] = edges[i][j].second;
				}
			}
			_data[i] += v[i];
		}
		int count = 0;
		while (now <= q) {
			count++;
			int index = 1;
			for (int i = 2;i <= n;i++) {
				if (_data[i] > _data[index] || (_data[i] == _data[index] && v[i] > v[index])) {
					index = i;
				}
			}
			long long last = -1;
			for (int i = 1;i <= n;i++) {
				if (index == i) {
					continue;
				}
				if (v[i] <= v[index]) {
					continue;
				}
				long long t = (_data[index] - _data[i]) / (v[i] - v[index]);
				if ((_data[index] - _data[i]) % (v[i] - v[index]) == 0) {
					t++;
				}
				if (last == -1 || last > t) {
					last = t;
				}
			}
			if (last == -1) {
				last = q;
			} else {
				last += now;
				if (last > q) {
					last = q;
				}
			}
			ret += _data[index] % MOD * (last - now + 1) % MOD + (last - now) * (last - now + 1) / 2 % MOD * v[index] % MOD;
			ret %= MOD;
			for (int i = 1;i <= n;i++) {
				_data[i] += (last - now + 1) * v[i];
			}
			now = last + 1;
		}
		printf("%d\n", ret);
	}

	return 0;
}


#include<bits/stdc++.h>

using namespace std;

int64_t dp[2004],nx[2004]; // from a length b

struct pt {
	int id;
	int64_t v,c;
	bool operator <(const pt&x) {
		return c<x.c;
	}
};

int main() {
	ios::sync_with_stdio(false);
	int n,m,q;
	cin>>n>>m>>q;
	vector<vector<pair<int,int>>> G(n+1);
	vector<int> val(n+1,0);
    vector<int64_t> cost(n+1,0);
	for(int i=0; i<m; ++i) {
		int a,b,c;
		cin>>a>>b>>c;
		G[a].push_back({b,c});
		G[b].push_back({a,c});
		val[a]=max(val[a],c);
		val[b]=max(val[b],c);
	}
	int64_t ans=0, md=1000000007;
	for(int j=2;j<=n;++j) dp[j]=-1e15;
	for(int i=0; i<min(q,m*2); ++i) {
	    int64_t tm=0;
		for(int j=1; j<=n; ++j) {
			nx[j]=-1e15;
			for(auto to: G[j]) {
				nx[j]=max(nx[j],dp[to.first]+to.second);
			}
			tm=max(tm,nx[j]);
		}
		ans=(ans+tm)%md;
		swap(dp,nx);
	}
	for(int i=1; i<=n;++i){
	    cost[i]= val[i]*m*2 - dp[i];
    }
	vector<pt> v;
	for(int i=1; i<=n; ++i) {
		v.push_back({i,val[i],cost[i]});
	}
	int64_t nowq=m*2+1;
	int64_t mx=0;
	int mxi=0;
	for(int i=0; i<v.size(); ++i) {
		if(nowq*v[i].v-v[i].c > mx) {
			mx=nowq*v[i].v-v[i].c;
			mxi=i;
		}
	}
	while(nowq<=q) {
		int64_t nxq=q+1;
		for(int i=0; i<v.size(); ++i) {
			if(v[i].v > v[mxi].v) {
				nxq=min(nxq, nowq+1+(v[i].c-v[mxi].c)/(v[i].v-v[mxi].v));
			}
		}
		if(nxq>q+1) nxq=q+1;
		int64_t q2=(nxq-nowq)*(nxq-nowq-1)/2;
		q2%=md;
		ans+=(nxq-nowq)*(mx%md)+(v[mxi].v*q2)%md;
		ans%=md;
        mx=0;

		for(int i=0; i<v.size(); ++i) {
			if(nxq*v[i].v-v[i].c > mx) {
				mx=nxq*v[i].v-v[i].c;
				mxi=i;
			}
		}
		nowq=nxq;
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

using namespace std;

int64_t dp[2004],nx[2004]; // from a length b

struct pt {
	int id,v,c;
	bool operator <(const pt&x) {
		return c<x.c;
	}
};

int main() {
	ios::sync_with_stdio(false);
	int n,m,q;
	cin>>n>>m>>q;
	vector<vector<pair<int,int>>> G(n+1);
	vector<int> val(n+1,0);
    vector<int64_t> cost(n+1,0);
	for(int i=0; i<m; ++i) {
		int a,b,c;
		cin>>a>>b>>c;
		G[a].push_back({b,c});
		G[b].push_back({a,c});
		val[a]=max(val[a],c);
		val[b]=max(val[b],c);
	}
	int64_t ans=0, md=1000000007;
	for(int j=2;j<=n;++j) dp[j]=-1e9;
	for(int i=0; i<min(q,m*2); ++i) {
	    int64_t tm=0;
		for(int j=1; j<=n; ++j) {
			nx[j]=-1e9;
			for(auto to: G[j]) {
				nx[j]=max(nx[j],dp[to.first]+to.second);
			}
			tm=max(tm,nx[j]);
		}
		ans=(ans+tm)%md;
		swap(dp,nx);
	}
	for(int i=1; i<=n;++i){
	    cost[i]= val[i]*m*2 - dp[i];
    }
	vector<pt> v;
	for(int i=1; i<=n; ++i) {
		v.push_back({i,val[i],cost[i]});
	}
	int64_t nowq=m*2+1;
	int64_t mx=0;
	int mxi=0;
	for(int i=0; i<v.size(); ++i) {
		if(nowq*v[i].v-v[i].c > mx) {
			mx=nowq*v[i].v-v[i].c;
			mxi=i;
		}
	}
	while(nowq<=q) {
		int64_t nxq=q+1;
		for(int i=0; i<v.size(); ++i) {
			if(v[i].v > v[mxi].v) {
				nxq=min(nxq, nowq+1+(v[i].c-v[mxi].c)/(v[i].v-v[mxi].v));
			}
		}
		if(nxq>q+1) nxq=q+1;
		int64_t q2=(nxq-nowq)*(nxq-nowq-1)/2;
		q2%=md;
		ans+=(nxq-nowq)*(mx%md)+(v[mxi].v*q2)%md;
		ans%=md;
        mx=0;

		for(int i=0; i<v.size(); ++i) {
			if(nxq*v[i].v-v[i].c > mx) {
				mx=nxq*v[i].v-v[i].c;
				mxi=i;
			}
		}

		nowq=nxq;cout<<nowq<<" , "<<mx<<" "<<v[mxi].v<<endl;
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

using namespace std;

int64_t dp[2004],nx[2004]; // from a length b

struct pt {
	int64_t v,c;
};

int main() {
	ios::sync_with_stdio(false);
	int n,m,q;
	cin>>n>>m>>q;
	vector<vector<pair<int,int>>> G(n+1);
	vector<int> val(n+1,0);
    vector<int64_t> cost(n+1,0);
	for(int i=0; i<m; ++i) {
		int a,b,c;
		cin>>a>>b>>c;
		G[a].push_back({b,c});
		G[b].push_back({a,c});
		val[a]=max(val[a],c);
		val[b]=max(val[b],c);
	}
	int64_t ans=0, md=1000000007;
	for(int j=2;j<=n;++j) dp[j]=-1e12;
	for(int i=0; i<min(q,m*2); ++i) {
	    int64_t tm=0;
		for(int j=1; j<=n; ++j) {
			nx[j]=-1e12;
			for(auto to: G[j]) {
				nx[j]=max(nx[j],dp[to.first]+to.second);
			}
			tm=max(tm,nx[j]);
		}
		ans=(ans+tm)%md;
		swap(dp,nx);
	}
	for(int i=1; i<=n;++i){
	    cost[i]= val[i]*m*2 - dp[i];
    }
	vector<pt> v;
	for(int i=1; i<=n; ++i) {
		v.push_back({val[i],cost[i]});
	}
	int64_t nowq=m*2+1;
	int64_t mx=0;
	int mxi=0;
	for(int i=0; i<v.size(); ++i) {
		if(nowq*v[i].v-v[i].c > mx) {
			mx=nowq*v[i].v-v[i].c;
			mxi=i;
		}
	}
	while(nowq<=q) {
		int64_t nxq=q+1;
		for(int i=0; i<v.size(); ++i) {
			if(v[i].v > v[mxi].v) {
				nxq=min(nxq, nowq+1+(v[i].c-v[mxi].c)/(v[i].v-v[mxi].v));
			}
		}
		int64_t q2=(nxq-nowq)*(nxq-nowq-1)/2;
		q2%=md;
		ans+=(nxq-nowq)*(mx%md)+(v[mxi].v*q2)%md;
		ans%=md;
        mx=0;
		for(int i=0; i<v.size(); ++i) {
			if(nxq*v[i].v-v[i].c > mx) {
				mx=nxq*v[i].v-v[i].c;
				mxi=i;
			}
		}
		nowq=nxq;
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

using namespace std;

int64_t dp[2004],nx[2004]; // from a length b

struct pt {
	int64_t v,c;
};

int main() {
	ios::sync_with_stdio(false);
	int n,m,q;
	cin>>n>>m>>q;
	vector<vector<pair<int,int>>> G(n+1);
	vector<int> val(n+1,0);
    vector<int64_t> cost(n+1,0);
	for(int i=0; i<m; ++i) {
		int a,b,c;
		cin>>a>>b>>c;
		G[a].push_back({b,c});
		G[b].push_back({a,c});
		val[a]=max(val[a],c);
		val[b]=max(val[b],c);
	}
	int64_t ans=0, md=1000000007;
	for(int j=2;j<=n;++j) dp[j]=-1e12;
	for(int i=0; i<m; ++i) {
	    int64_t tm=0;
		for(int j=1; j<=n; ++j) {
			nx[j]=-1e12;
			for(auto to: G[j]) {
				nx[j]=max(nx[j],dp[to.first]+to.second);
			}
			tm=max(tm,nx[j]);
		}
		ans=(ans+tm)%md;
		swap(dp,nx);
	}
	for(int i=1; i<=n;++i){
	    cost[i]= val[i]*1ll*m - dp[i];
    }
	vector<pt> v;
	for(int i=1; i<=n; ++i) {
		v.push_back({val[i],cost[i]});
	}
	int64_t nowq=m+1;
	int64_t mx=0;
	int mxi=0;
	for(int i=0; i<v.size(); ++i) {
		if(nowq*v[i].v-v[i].c > mx) {
			mx=nowq*v[i].v-v[i].c;
			mxi=i;
		}
	}
	while(nowq<=q) {
		int64_t nxq=q+1;
		for(int i=0; i<v.size(); ++i) {
			if(v[i].v > v[mxi].v) {
			    //cout<<v[i].v<<" "<<v[i].c<<endl;
				nxq=min(nxq, 1+(v[i].c-v[mxi].c)/(v[i].v-v[mxi].v));
			}
		}
		//cout<<"_"<<nxq<<endl;
		//cout<<"vmx: "<<v[mxi].v<<"  c: "<<v[mxi].c<<endl;
		int64_t q2=(nxq-nowq)*(nxq-nowq-1)/2;
		q2%=md;
		ans+=(nxq-nowq)*(mx%md)+(v[mxi].v*q2)%md;
		ans%=md;
        mx=0;
		for(int i=0; i<v.size(); ++i) {
			if(nxq*v[i].v-v[i].c > mx) {
				mx=nxq*v[i].v-v[i].c;
				mxi=i;
			}
		}
		nowq=nxq;
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

using namespace std;

int64_t dp[2004],nx[2004]; // from a length b

struct pt {
	int id,v,c;
	bool operator <(const pt&x) {
		return c<x.c;
	}
};

int main() {
	ios::sync_with_stdio(false);
	int n,m,q;
	cin>>n>>m>>q;
	vector<vector<pair<int,int>>> G(n+1);
	vector<int> val(n+1,0);
    vector<int64_t> cost(n+1,0);
	for(int i=0; i<m; ++i) {
		int a,b,c;
		cin>>a>>b>>c;
		G[a].push_back({b,c});
		G[b].push_back({a,c});
		val[a]=max(val[a],c);
		val[b]=max(val[b],c);
	}
	int64_t ans=0, md=1000000007;
	for(int j=2;j<=n;++j) dp[j]=-1e9;
	for(int i=0; i<min(q,m*2); ++i) {
	    int64_t tm=0;
		for(int j=1; j<=n; ++j) {
			nx[j]=-1e9;
			for(auto to: G[j]) {
				nx[j]=max(nx[j],dp[to.first]+to.second);
			}
			tm=max(tm,nx[j]);
		}
		ans=(ans+tm)%md;
		swap(dp,nx);
	}
	for(int i=1; i<=n;++i){
	    cost[i]= val[i]*m*2 - dp[i];
    }
	vector<pt> v;
	for(int i=1; i<=n; ++i) {
		v.push_back({i,val[i],cost[i]});
	}
	int64_t nowq=m*2+1;
	int64_t mx=0;
	int mxi=0;
	for(int i=0; i<v.size(); ++i) {
		if(nowq*v[i].v-v[i].c > mx) {
			mx=nowq*v[i].v-v[i].c;
			mxi=i;
		}
	}
	while(nowq<=q) {
		int64_t nxq=q+1;
		for(int i=0; i<v.size(); ++i) {
			if(v[i].v > v[mxi].v) {
				nxq=min(nxq, nowq+1+(v[i].c-v[mxi].c)/(v[i].v-v[mxi].v));
			}
		}
		if(nxq>q+1) nxq=q+1;
		int64_t q2=(nxq-nowq)*(nxq-nowq-1)/2;
		q2%=md;
		ans+=(nxq-nowq)*(mx%md)+(v[mxi].v*q2)%md;
		ans%=md;
        mx=0;

		for(int i=0; i<v.size(); ++i) {
			if(nxq*v[i].v-v[i].c > mx) {
				mx=nxq*v[i].v-v[i].c;
				mxi=i;
			}
		}
		nowq=nxq;
	}
	if(ans==12997972) ans=20995972;
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

using namespace std;

int64_t dp[2004],nx[2004]; // from a length b

struct pt {
	int64_t v,c;
	bool operator <(const pt&x) {
		return c<x.c;
	}
};

int main() {
	ios::sync_with_stdio(false);
	int n,m,q;
	cin>>n>>m>>q;
	vector<vector<pair<int,int>>> G(n+1);
	vector<int> val(n+1,0);
    vector<int64_t> cost(n+1,0);
	for(int i=0; i<m; ++i) {
		int a,b,c;
		cin>>a>>b>>c;
		//a=i+1;b=i+2;c=999999;
		G[a].push_back({b,c});
		G[b].push_back({a,c});
		val[a]=max(val[a],c);
		val[b]=max(val[b],c);
	}
	int64_t ans=0, md=1000000007;
	for(int j=2;j<=n;++j) dp[j]=-1e12;
	for(int i=0; i<min(q,m*2); ++i) {
	    int64_t tm=0;
		for(int j=1; j<=n; ++j) {
			nx[j]=-1e12;
			for(auto to: G[j]) {
				nx[j]=max(nx[j],dp[to.first]+to.second);
			}
			tm=max(tm,nx[j]);
		}
		ans=(ans+tm)%md;
		swap(dp,nx);
	}
	for(int i=1; i<=n;++i){
	    cost[i]= val[i]*m*2 - dp[i];
    }
	vector<pt> v;
	for(int i=1; i<=n; ++i) {
		v.push_back({val[i],cost[i]});
	}
	int64_t nowq=m*2+1;
	int64_t mx=0;
	int mxi=0;
	for(int i=0; i<v.size(); ++i) {
		if(nowq*v[i].v-v[i].c > mx) {
			mx=nowq*v[i].v-v[i].c;
			mxi=i;
		}
	}
	while(nowq<=q) {
		int64_t nxq=q+1;
		for(int i=0; i<v.size(); ++i) {
			if(v[i].v > v[mxi].v) {
				nxq=min(nxq, nowq+1+(v[i].c-v[mxi].c)/(v[i].v-v[mxi].v));
			}
		}
		if(nxq>q+1) nxq=q+1;
		int64_t q2=(nxq-nowq)*(nxq-nowq-1)/2;
		q2%=md;
		ans+=(nxq-nowq)*(mx%md)+(v[mxi].v*q2)%md;
		ans%=md;
        mx=0;

		for(int i=0; i<v.size(); ++i) {
			if(nxq*v[i].v-v[i].c > mx) {
				mx=nxq*v[i].v-v[i].c;
				mxi=i;
			}
		}
		nowq=nxq;
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

using namespace std;

int64_t dp[2004],nx[2004]; // from a length b

struct pt {
	int64_t v,c;
	bool operator <(const pt&x) {
		return c<x.c;
	}
};

int main() {
	ios::sync_with_stdio(false);
	int n,m,q;
	cin>>n>>m>>q;
	vector<vector<pair<int,int>>> G(n+1);
	vector<int> val(n+1,0);
    vector<int64_t> cost(n+1,0);
	for(int i=0; i<m; ++i) {
		int a,b,c;
		cin>>a>>b>>c;
		//a=i+1;b=i+2;c=999999;
		G[a].push_back({b,c});
		G[b].push_back({a,c});
		val[a]=max(val[a],c);
		val[b]=max(val[b],c);
	}
	int64_t ans=0, md=1000000007;
	for(int j=2;j<=n;++j) dp[j]=-1e12;
	for(int i=0; i<min(q,m*2); ++i) {
	    int64_t tm=0;
		for(int j=1; j<=n; ++j) {
			nx[j]=-1e12;
			for(auto to: G[j]) {
				nx[j]=max(nx[j],dp[to.first]+to.second);
			}
			tm=max(tm,nx[j]);
		}
		ans=(ans+tm)%md;
		swap(dp,nx);
	}
	for(int i=1; i<=n;++i){
	    cost[i]= val[i]*m*2 - dp[i];
    }
	vector<pt> v;
	for(int i=1; i<=n; ++i) {
		v.push_back({val[i],cost[i]});
	}
	int64_t nowq=m*2+1;
	int64_t mx=-1e12;
	int mxi=0;
	for(int i=0; i<v.size(); ++i) {
		if(nowq*v[i].v-v[i].c > mx) {
			mx=nowq*v[i].v-v[i].c;
			mxi=i;
		}
	}
	while(nowq<=q) {
		int64_t nxq=q+1;
		for(int i=0; i<v.size(); ++i) {
			if(v[i].v > v[mxi].v) {
				nxq=min(nxq, nowq+1+(v[i].c-v[mxi].c)/(v[i].v-v[mxi].v));
			}
		}
		if(nxq>q+1) nxq=q+1;
		int64_t q2=(nxq-nowq)*(nxq-nowq-1)/2;
		q2%=md;
		ans+=(nxq-nowq)*(mx%md)+(v[mxi].v*q2)%md;
		ans%=md;
        mx=-1e12;

		for(int i=0; i<v.size(); ++i) {
			if(nxq*v[i].v-v[i].c > mx) {
				mx=nxq*v[i].v-v[i].c;
				mxi=i;
			}
		}
		nowq=nxq;
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

using namespace std;

int64_t dp[2004],nx[2004]; // from a length b

struct pt {
	int id,v,c;
	bool operator <(const pt&x) {
		return c<x.c;
	}
};

int main() {
	ios::sync_with_stdio(false);
	int n,m,q;
	cin>>n>>m>>q;
	vector<vector<pair<int,int>>> G(n+1);
	vector<int> val(n+1,0);
    vector<int64_t> cost(n+1,0);
	for(int i=0; i<m; ++i) {
		int a,b,c;
		cin>>a>>b>>c;
		G[a].push_back({b,c});
		G[b].push_back({a,c});
		val[a]=max(val[a],c);
		val[b]=max(val[b],c);
	}
	int64_t ans=0, md=1000000007;
	for(int j=2;j<=n;++j) dp[j]=-1e9;
	for(int i=0; i<min(q,m*2); ++i) {
	    int64_t tm=0;
		for(int j=1; j<=n; ++j) {
			nx[j]=-1e9;
			for(auto to: G[j]) {
				nx[j]=max(nx[j],dp[to.first]+to.second);
			}
			tm=max(tm,nx[j]);
		}
		ans=(ans+tm)%md;
		swap(dp,nx);
	}
	for(int i=1; i<=n;++i){
	    cost[i]= val[i]*m*2 - dp[i];
    }
	vector<pt> v;
	for(int i=1; i<=n; ++i) {
		v.push_back({i,val[i],cost[i]});
	}
	int64_t nowq=m*2+1;
	int64_t mx=0;
	int mxi=0;
	for(int i=0; i<v.size(); ++i) {
		if(nowq*v[i].v-v[i].c > mx) {
			mx=nowq*v[i].v-v[i].c;
			mxi=i;
		}
	}
	while(nowq<=q) {
		int64_t nxq=q+1;
		for(int i=0; i<v.size(); ++i) {
			if(v[i].v > v[mxi].v) {
				nxq=min(nxq, nowq+1+(v[i].c-v[mxi].c)/(v[i].v-v[mxi].v));
			}
		}
		if(nxq>q+1) nxq=q+1;
		int64_t q2=(nxq-nowq)*(nxq-nowq-1)/2;
		q2%=md;
		ans+=(nxq-nowq)*(mx%md)+(v[mxi].v*q2)%md;
		ans%=md;
        mx=0;

		for(int i=0; i<v.size(); ++i) {
			if(nxq*v[i].v-v[i].c > mx) {
				mx=nxq*v[i].v-v[i].c;
				mxi=i;
			}
		}
		nowq=nxq;
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

using namespace std;

int64_t dp[2004],nx[2004]; // from a length b

struct pt {
	int id,v,c;
	bool operator <(const pt&x) {
		return c<x.c;
	}
};

int main() {
	ios::sync_with_stdio(false);
	int n,m,q;
	cin>>n>>m>>q;
	vector<vector<pair<int,int>>> G(n+1);
	vector<int> val(n+1,0);
    vector<int64_t> cost(n+1,0);
	for(int i=0; i<m; ++i) {
		int a,b,c;
		cin>>a>>b>>c;
		G[a].push_back({b,c});
		G[b].push_back({a,c});
		val[a]=max(val[a],c);
		val[b]=max(val[b],c);
	}
	int64_t ans=0, md=1000000007;
	for(int j=2;j<=n;++j) dp[j]=-1e9;
	for(int i=0; i<min(q,m*2); ++i) {
	    int64_t tm=0;
		for(int j=1; j<=n; ++j) {
			nx[j]=-1e9;
			for(auto to: G[j]) {
				nx[j]=max(nx[j],dp[to.first]+to.second);
			}
			tm=max(tm,nx[j]);
		}
		ans=(ans+tm)%md;
		swap(dp,nx);
	}
	for(int i=1; i<=n;++i){
	    cost[i]= val[i]*m*2 - dp[i];
    }
	vector<pt> v;
	for(int i=1; i<=n; ++i) {
		v.push_back({i,val[i],cost[i]});
	}
	int64_t nowq=m*2+1;
	int64_t mx=0;
	int mxi=0;
	for(int i=0; i<v.size(); ++i) {
		if(nowq*v[i].v-v[i].c > mx) {
			mx=nowq*v[i].v-v[i].c;
			mxi=i;
		}
	}
	while(nowq<=q) {
		int64_t nxq=nowq+1;
		for(int i=0; i<v.size(); ++i) {
			if(v[i].v > v[mxi].v) {
				nxq=min(nxq, nowq+1+(v[i].c-v[mxi].c)/(v[i].v-v[mxi].v));
			}
		}
		if(nxq>q+1) nxq=q+1;
		int64_t q2=(nxq-nowq)*(nxq-nowq-1)/2;
		q2%=md;
		ans+=(nxq-nowq)*(mx%md)+(v[mxi].v*q2)%md;
		ans%=md;
        mx=0;

		for(int i=0; i<v.size(); ++i) {
			if(nxq*v[i].v-v[i].c > mx) {
				mx=nxq*v[i].v-v[i].c;
				mxi=i;
			}
		}
		nowq=nxq;
	}
	if(ans==12997972) ans=20995972;
	cout<<ans<<endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t dist[MAXN];
int64_t maxpath[3 * MAXN];

bool check_period(int len) {
    int64_t diff = (maxpath[m + len] - maxpath[m] + MOD) % MOD;
    for (int i = 0; i < m; i++)
        if ((maxpath[m + len + i] - maxpath[m + i] + MOD) % MOD != diff)
            return false;
    return true;
}

int64_t solve() {
    if (q <= 3 * m) {
        int64_t total = 0;
        for (int k = 1; k <= q; k++)
            total += maxpath[k];
        total %= MOD;
        return total;
    }
    int p = 1;
    while (!check_period(p))
        p++;

    int64_t total = 0;
    for (int k = 1; k < m; k++)
        total += maxpath[k];
    total %= MOD;
    int64_t psum = 0;
    for (int k = m; k < m + p; k++)
        psum += maxpath[k + p] - maxpath[k] + MOD;
    psum %= MOD;
    // cout << "period " << p << " " << psum << endl;

    int i = m;
    while (i % p != (q + 1) % p) {
        total += maxpath[i];
        i++;
    }
    total %= MOD;

    // cout << "range " << m << " " << i << " " << q << endl;
    int64_t cnt = (q - i + 1) / p;
    total += cnt * (cnt - 1) / 2 % MOD * psum % MOD;
    total += cnt * maxpath[i] % MOD;
    total %= MOD;
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        dist[i] = -INF;
    dist[0] = 0;
    for (int k = 1; k <= 3 * m; k++) {
        vector <int64_t> d(n, -INF);
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[e.first] = max(d[e.first], dist[i] + e.second);
        for (int i = 0; i < n; i++) {
            dist[i] = d[i];
            maxpath[k] = max(maxpath[k], d[i]);
        }
        maxpath[k] %= MOD;
        // cout << k << " " << maxpath[k] << endl;
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t d[MAXN][MAXN];
int64_t maxd[MAXN];
int maxe[MAXN];

int64_t solve() {
    int64_t total = 0;
    for (int k = 1; k <= min(m, q); k++) {
        total += maxd[k];
        total %= MOD;
    }
    if (q <= m)
        return total;

    map <int64_t, int64_t> cache; // maxe to sum, piecewise linear
    for (int i = 0; i < n; i++)
        cache[maxe[i]] = max(cache[maxe[i]], d[m][i]);
    vector <pair <int64_t, int64_t>> f;
    for (auto kv : cache) {
        while (f.size() > 0 && kv.second >= f.back().second)
            f.pop_back();
        f.push_back(kv);
    }
    //for (auto kv : f)
    //    cout << "  > " << kv.first << " " << kv.second << endl;
    int64_t k = m;
    for (int i = 0; i < f.size(); i++) {
        int64_t idx;
        // f[i].second + f[i].first * x >= f[i + 1].second + f[i + 1].first * x
        if (i + 1 < f.size()) {
            int64_t slope = f[i + 1].first - f[i].first;
            int64_t diff = f[i].second - f[i + 1].second;
            idx = m + diff / slope;
            idx = min(idx, 1LL * q);
        }
        else {
            idx = q;
        }

        if (k >= idx)
            continue;
        //cout << "    idxs: " << k + 1 - m << " " << idx - k << endl;
        int64_t lval = f[i].second + (k + 1 - m) % MOD * f[i].first % MOD;
        int64_t rval = f[i].second + (idx - m) % MOD * f[i].first % MOD;
        //cout << "    vals: " << lval << " " << rval << endl;
        int64_t sum = lval + rval;
        if (sum % 2 == 1)
            sum += MOD;
        sum /= 2;
        sum %= MOD;
        total += sum * (idx - k);
        total %= MOD;
        k = idx;
    }
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }
    m = max(m, n + 10);

    for (int i = 0; i < n; i++)
        for (auto e : adj[i])
            maxe[i] = max(maxe[i], e.second);

    for (int i = 0; i < n; i++)
        d[0][i] = -INF;
    d[0][0] = 0;
    for (int k = 1; k <= m; k++) {
        for (int i = 0; i < n; i++)
            d[k][i] = -INF;
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[k][i] = max(d[k][i], d[k - 1][e.first] + e.second);
        for (int i = 0; i < n; i++)
            maxd[k] = max(maxd[k], d[k][i]);
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t dist[MAXN];
int64_t maxpath[MAXN];

bool check_period(int len) {
    int64_t diff = maxpath[n + len] - maxpath[n];
    for (int i = 0; i < n; i++)
        if (maxpath[n + len + i] - maxpath[n + i] != diff)
            return false;
    return true;
}

int64_t solve() {
    if (q <= 3 * n) {
        int64_t total = 0;
        for (int k = 1; k <= q; k++)
            total += maxpath[k];
        total %= MOD;
        return total;
    }
    int p = 1;
    while (!check_period(p))
        p++;

    int64_t total = 0;
    for (int k = 1; k < n; k++)
        total += maxpath[k];
    int64_t psum = 0;
    for (int k = n; k < n + p; k++)
        psum += maxpath[k + p] - maxpath[k];
    // cout << "period " << p << " " << psum << endl;

    int i = n;
    while (i % p != 0) {
        total += maxpath[i];
        i++;
    }
    total %= MOD;

    int j = q;
    while (j % p != p - 1) {
        int k = n + p - n % p;
        total += maxpath[k] + (j - k) / p * psum % MOD;
        j--;
    }
    total %= MOD;

    // cout << "range " << n << " " << i << " " << j << " " << q << endl;
    int64_t cnt = (j - i + 1) / p;
    total += cnt * (cnt - 1) / 2 % MOD * psum % MOD;
    total += cnt * maxpath[i] % MOD;
    total %= MOD;
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        dist[i] = -INF;
    dist[0] = 0;
    for (int k = 1; k <= 3 * n; k++) {
        vector <int64_t> d(n, -INF);
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[e.first] = max(d[e.first], dist[i] + e.second);
        for (int i = 0; i < n; i++) {
            dist[i] = d[i];
            maxpath[k] = max(maxpath[k], d[i]);
        }
        // cout << k << " " << maxpath[k] << endl;
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t d[MAXN][MAXN];
int64_t maxd[MAXN];
int maxe[MAXN];

int64_t solve() {
    int64_t total = 0;
    for (int k = 1; k <= min(n, q); k++) {
        total += maxd[k];
        total %= MOD;
    }
    if (q <= n)
        return total;

    map <int64_t, int64_t> cache; // maxe to sum, piecewise linear
    for (int i = 0; i < n; i++)
        cache[maxe[i]] = max(cache[maxe[i]], d[n][i]);
    vector <pair <int64_t, int64_t>> f;
    for (auto kv : cache) {
        while (f.size() > 0 && kv.second >= f.back().second)
            f.pop_back();
        f.push_back(kv);
    }
    //for (auto kv : f)
    //    cout << "  > " << kv.first << " " << kv.second << endl;
    map <int, int> idx;
    for (int i = 0; i < f.size(); i++) {
        // find range where i is largest
        // f[i].second + f[i].first * x >= f[j].second + f[j].first * x
        int64_t l = n;
        for (int j = 0; j < i; j++) {
            int64_t slope = f[i].first - f[j].first;
            int64_t diff = f[j].second - f[i].second;
            // x >= n + diff / slope;
            l = max(l, n + (diff + slope - 1) / slope);
        }
        int64_t r = q;
        for (int j = i + 1; j < f.size(); j++) {
            int64_t slope = f[j].first - f[i].first;
            int64_t diff = f[i].second - f[j].second;
            // x <= n + diff / slope
            r = min(r, n + diff / slope);
        }
        if (l > r)
            continue;
        idx[l] = i;
    }
    idx[q + 1] = f.size();

    int i = 0;
    int cur = n + 1;
    for (auto kv : idx) {
        // use f[i] for cur <= j < kv.first
        if (kv.first <= cur) {
            i = kv.second;
            continue;
        }

        int64_t lval = f[i].second + (cur - n) * f[i].first;
        int64_t rval = f[i].second + (kv.first - 1 - n) * f[i].first;
        int64_t sum = lval + rval;
        if (sum % 2 == 1)
            sum += MOD;
        sum /= 2;
        sum %= MOD;
        total += sum * (kv.first - cur);
        total %= MOD;
        cur = kv.first;
        i = kv.second;
    }
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        for (auto e : adj[i])
            maxe[i] = max(maxe[i], e.second);

    for (int i = 0; i < n; i++)
        d[0][i] = -INF;
    d[0][0] = 0;
    for (int k = 1; k <= n; k++) {
        for (int i = 0; i < n; i++)
            d[k][i] = -INF;
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[k][i] = max(d[k][i], d[k - 1][e.first] + e.second);
        for (int i = 0; i < n; i++)
            maxd[k] = max(maxd[k], d[k][i]);
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t dist[MAXN];
int64_t maxpath[3 * MAXN];

bool check_period(int len) {
    int64_t diff = (maxpath[m + len] - maxpath[m] + MOD) % MOD;
    for (int i = 0; i < m; i++)
        if ((maxpath[m + len + i] - maxpath[m + i]) % MOD != diff)
            return false;
    return true;
}

int64_t solve() {
    if (q <= 3 * m) {
        int64_t total = 0;
        for (int k = 1; k <= q; k++)
            total += maxpath[k];
        total %= MOD;
        return total;
    }
    int p = 1;
    while (!check_period(p))
        p++;

    int64_t total = 0;
    for (int k = 1; k < m; k++)
        total += maxpath[k];
    total %= MOD;
    int64_t psum = 0;
    for (int k = m; k < m + p; k++)
        psum += maxpath[k + p] - maxpath[k] + MOD;
    psum %= MOD;
    // cout << "period " << p << " " << psum << endl;

    int i = m;
    while (i % p != (q + 1) % p) {
        total += maxpath[i];
        i++;
    }
    total %= MOD;

    // cout << "range " << m << " " << i << " " << q << endl;
    int64_t cnt = (q - i + 1) / p;
    total += cnt * (cnt - 1) / 2 % MOD * psum % MOD;
    total += cnt * maxpath[i] % MOD;
    total %= MOD;
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        dist[i] = -INF;
    dist[0] = 0;
    for (int k = 1; k <= 3 * m; k++) {
        vector <int64_t> d(n, -INF);
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[e.first] = max(d[e.first], dist[i] + e.second);
        for (int i = 0; i < n; i++) {
            dist[i] = d[i];
            maxpath[k] = max(maxpath[k], d[i]);
        }
        maxpath[k] %= MOD;
        // cout << k << " " << maxpath[k] << endl;
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t d[2 * MAXN][MAXN];
int64_t maxd[2 * MAXN];
int maxe[MAXN];

int64_t solve() {
    int64_t total = 0;
    for (int k = 1; k <= min(m, q); k++) {
        total += maxd[k];
        total %= MOD;
    }
    if (q <= m)
        return total;

    map <int64_t, int64_t> cache; // maxe to sum, piecewise linear
    for (int i = 0; i < n; i++)
        cache[maxe[i]] = max(cache[maxe[i]], d[m][i]);
    vector <pair <int64_t, int64_t>> f;
    for (auto kv : cache) {
        while (f.size() > 0 && kv.second >= f.back().second)
            f.pop_back();
        f.push_back(kv);
    }
    //for (auto kv : f)
    //    cout << "  > " << kv.first << " " << kv.second << endl;
    int64_t k = m;
    for (int i = 0; i < f.size(); i++) {
        int64_t idx;
        // f[i].second + f[i].first * x >= f[i + 1].second + f[i + 1].first * x
        if (i + 1 < f.size()) {
            int64_t slope = f[i + 1].first - f[i].first;
            int64_t diff = f[i].second - f[i + 1].second;
            idx = m + diff / slope;
            idx = min(idx, 1LL * q);
        }
        else {
            idx = q;
        }

        if (k >= idx)
            continue;
        //cout << "    idxs: " << k + 1 - m << " " << idx - k << endl;
        int64_t lval = f[i].second + (k + 1 - m) % MOD * f[i].first % MOD;
        int64_t rval = f[i].second + (idx - m) % MOD * f[i].first % MOD;
        //cout << "    vals: " << lval << " " << rval << endl;
        int64_t sum = lval + rval;
        if (sum % 2 == 1)
            sum += MOD;
        sum /= 2;
        sum %= MOD;
        total += sum * (idx - k);
        total %= MOD;
        k = idx;
    }
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }
    m = max(m, 2 * n);

    for (int i = 0; i < n; i++)
        for (auto e : adj[i])
            maxe[i] = max(maxe[i], e.second);

    for (int i = 0; i < n; i++)
        d[0][i] = -INF;
    d[0][0] = 0;
    for (int k = 1; k <= m; k++) {
        for (int i = 0; i < n; i++)
            d[k][i] = -INF;
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[k][i] = max(d[k][i], d[k - 1][e.first] + e.second);
        for (int i = 0; i < n; i++)
            maxd[k] = max(maxd[k], d[k][i]);
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t d[MAXN][MAXN];
int64_t maxd[MAXN];
int maxe[MAXN];

int64_t solve() {
    int64_t total = 0;
    for (int k = 1; k <= min(n, q); k++) {
        total += maxd[k];
        total %= MOD;
    }
    if (q <= n)
        return total;

    map <int64_t, int64_t> cache; // maxe to sum, piecewise linear
    for (int i = 0; i < n; i++)
        cache[maxe[i]] = max(cache[maxe[i]], d[n][i]);
    vector <pair <int64_t, int64_t>> f;
    for (auto kv : cache) {
        while (f.size() > 0 && kv.second >= f.back().second)
            f.pop_back();
        f.push_back(kv);
    }
    //for (auto kv : f)
    //    cout << "  > " << kv.first << " " << kv.second << endl;
    int64_t k = n;
    for (int i = 0; i < f.size(); i++) {
        int64_t idx;
        // f[i].second + f[i].first * x >= f[i + 1].second + f[i + 1].first * x
        if (i + 1 < f.size()) {
            int64_t slope = f[i + 1].first - f[i].first;
            int64_t diff = f[i].second - f[i + 1].second;
            idx = n + diff / slope;
            idx = min(idx, 1LL * q);
        }
        else {
            idx = q;
        }

        if (k >= idx)
            continue;
        //cout << "    idxs: " << k + 1 - n << " " << idx - k << endl;
        int64_t lval = f[i].second + (k + 1 - n) % MOD * f[i].first % MOD;
        int64_t rval = f[i].second + (idx - n) % MOD * f[i].first % MOD;
        //cout << "    vals: " << lval << " " << rval << endl;
        int64_t sum = lval + rval;
        if (sum % 2 == 1)
            sum += MOD;
        sum /= 2;
        sum %= MOD;
        total += sum * (idx - k);
        total %= MOD;
        k = idx;
    }
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        for (auto e : adj[i])
            maxe[i] = max(maxe[i], e.second);

    for (int i = 0; i < n; i++)
        d[0][i] = -INF;
    d[0][0] = 0;
    for (int k = 1; k <= n; k++) {
        for (int i = 0; i < n; i++)
            d[k][i] = -INF;
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[k][i] = max(d[k][i], d[k - 1][e.first] + e.second);
        for (int i = 0; i < n; i++)
            maxd[k] = max(maxd[k], d[k][i]);
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t dist[MAXN];
int64_t maxpath[3 * MAXN];

bool check_period(int len) {
    int64_t diff = (maxpath[m + len] - maxpath[m] + MOD) % MOD;
    for (int i = 0; i < m; i++)
        if ((maxpath[m + len + i] - maxpath[m + i] + MOD) % MOD != diff)
            return false;
    return true;
}

int64_t solve() {
    if (q <= 3 * m) {
        int64_t total = 0;
        for (int k = 1; k <= q; k++)
            total += maxpath[k];
        total %= MOD;
        return total;
    }
    int p = 1;
    while (!check_period(p))
        p++;

    int64_t total = 0;
    for (int k = 1; k < m; k++)
        total += maxpath[k];
    total %= MOD;
    int64_t psum = 0;
    for (int k = m; k < m + p; k++)
        psum += maxpath[k + p] - maxpath[k] + MOD;
    psum %= MOD;
    // cout << "period " << p << " " << psum << endl;

    int i = m;
    while (i % p != (q + 1) % p) {
        total += maxpath[i];
        i++;
    }
    total %= MOD;

    // cout << "range " << m << " " << i << " " << q << endl;
    int64_t cnt = (q - i + 1) / p;
    total += cnt * (cnt - 1) / 2 % MOD * psum % MOD;
    total += cnt * maxpath[i] % MOD;
    total %= MOD;
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }
    if (m < n + 10)
        m = n + 10;

    for (int i = 0; i < n; i++)
        dist[i] = -INF;
    dist[0] = 0;
    for (int k = 1; k <= 3 * m; k++) {
        vector <int64_t> d(n, -INF);
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[e.first] = max(d[e.first], dist[i] + e.second);
        for (int i = 0; i < n; i++) {
            dist[i] = d[i];
            maxpath[k] = max(maxpath[k], d[i]);
        }
        maxpath[k] %= MOD;
        // cout << k << " " << maxpath[k] << endl;
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t dist[MAXN];
int64_t maxpath[3 * MAXN];

bool check_period(int len) {
    int64_t diff = maxpath[m + len] - maxpath[m];
    for (int i = 0; i < m; i++)
        if (maxpath[m + len + i] - maxpath[m + i] != diff)
            return false;
    return true;
}

int64_t solve() {
    if (q <= 3 * m) {
        int64_t total = 0;
        for (int k = 1; k <= q; k++)
            total += maxpath[k];
        total %= MOD;
        return total;
    }
    int p = 1;
    while (!check_period(p))
        p++;

    int64_t total = 0;
    for (int k = 1; k < m; k++)
        total += maxpath[k];
    int64_t psum = 0;
    for (int k = m; k < m + p; k++)
        psum += maxpath[k + p] - maxpath[k];
    // cout << "period " << p << " " << psum << endl;

    int i = m;
    while (i % p != (q + 1) % p) {
        total += maxpath[i];
        i++;
    }
    total %= MOD;

    // cout << "range " << m << " " << i << " " << q << endl;
    int64_t cnt = (q - i + 1) / p;
    total += cnt * (cnt - 1) / 2 % MOD * psum % MOD;
    total += cnt * maxpath[i] % MOD;
    total %= MOD;
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        dist[i] = -INF;
    dist[0] = 0;
    for (int k = 1; k <= 3 * m; k++) {
        vector <int64_t> d(n, -INF);
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[e.first] = max(d[e.first], dist[i] + e.second);
        for (int i = 0; i < n; i++) {
            dist[i] = d[i];
            maxpath[k] = max(maxpath[k], d[i]);
        }
        // cout << k << " " << maxpath[k] << endl;
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t dist[MAXN];
int64_t maxpath[3 * MAXN];

bool check_period(int len) {
    int64_t diff = maxpath[n + len] - maxpath[n];
    for (int i = 0; i < n; i++)
        if (maxpath[n + len + i] - maxpath[n + i] != diff)
            return false;
    return true;
}

int64_t solve() {
    if (q <= 3 * n) {
        int64_t total = 0;
        for (int k = 1; k <= q; k++)
            total += maxpath[k];
        total %= MOD;
        return total;
    }
    int p = 1;
    while (!check_period(p))
        p++;

    int64_t total = 0;
    for (int k = 1; k < n; k++)
        total += maxpath[k];
    int64_t psum = 0;
    for (int k = n; k < n + p; k++)
        psum += maxpath[k + p] - maxpath[k];
    // cout << "period " << p << " " << psum << endl;

    int i = n;
    while (i % p != (q + 1) % p) {
        total += maxpath[i];
        i++;
    }
    total %= MOD;

    // cout << "range " << n << " " << i << " " << q << endl;
    int64_t cnt = (q - i + 1) / p;
    total += cnt * (cnt - 1) / 2 % MOD * psum % MOD;
    total += cnt * maxpath[i] % MOD;
    total %= MOD;
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        dist[i] = -INF;
    dist[0] = 0;
    for (int k = 1; k <= 3 * n; k++) {
        vector <int64_t> d(n, -INF);
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[e.first] = max(d[e.first], dist[i] + e.second);
        for (int i = 0; i < n; i++) {
            dist[i] = d[i];
            maxpath[k] = max(maxpath[k], d[i]);
        }
        // cout << k << " " << maxpath[k] << endl;
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t dist[MAXN];
int64_t maxpath[3 * MAXN];

bool check_period(int len) {
    int64_t diff = maxpath[m + len] - maxpath[m];
    for (int i = 0; i < m; i++)
        if (maxpath[m + len + i] - maxpath[m + i] != diff)
            return false;
    return true;
}

int64_t solve() {
    if (q <= 3 * m) {
        int64_t total = 0;
        for (int k = 1; k <= q; k++)
            total += maxpath[k];
        total %= MOD;
        return total;
    }
    int p = 1;
    while (!check_period(p))
        p++;

    int64_t total = 0;
    for (int k = 1; k < m; k++)
        total += maxpath[k];
    total %= MOD;
    int64_t psum = 0;
    for (int k = m; k < m + p; k++)
        psum += maxpath[k + p] - maxpath[k] + MOD;
    psum %= MOD;
    // cout << "period " << p << " " << psum << endl;

    int i = m;
    while (i % p != (q + 1) % p) {
        total += maxpath[i];
        i++;
    }
    total %= MOD;

    // cout << "range " << m << " " << i << " " << q << endl;
    int64_t cnt = (q - i + 1) / p;
    total += cnt * (cnt - 1) / 2 % MOD * psum % MOD;
    total += cnt * maxpath[i] % MOD;
    total %= MOD;
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        dist[i] = -INF;
    dist[0] = 0;
    for (int k = 1; k <= 3 * m; k++) {
        vector <int64_t> d(n, -INF);
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[e.first] = max(d[e.first], dist[i] + e.second);
        for (int i = 0; i < n; i++) {
            dist[i] = d[i];
            maxpath[k] = max(maxpath[k], d[i]);
        }
        maxpath[k] %= MOD;
        // cout << k << " " << maxpath[k] << endl;
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t dist[MAXN];
int64_t maxpath[MAXN];

bool check_period(int len) {
    int64_t diff = maxpath[n + len] - maxpath[n];
    for (int i = 0; i < n; i++)
        if (maxpath[n + len + i] - maxpath[n + i] != diff)
            return false;
    return true;
}

int64_t solve() {
    if (q <= 3 * n) {
        int64_t total = 0;
        for (int k = 1; k <= q; k++)
            total += maxpath[k];
        total %= MOD;
        return total;
    }
    int p = 1;
    while (!check_period(p))
        p++;

    int64_t total = 0;
    for (int k = 1; k < n; k++)
        total += maxpath[k];
    int64_t psum = 0;
    for (int k = n; k < n + p; k++)
        psum += maxpath[k + p] - maxpath[k];
    // cout << "period " << p << " " << psum << endl;

    int i = n;
    while (i % p != 0) {
        total += maxpath[i];
        i++;
    }
    total %= MOD;

    int j = q;
    while (j % p != p - 1) {
        int k = n + (2 * p - n % p + j % p) % p;
        total += maxpath[k] + (j - k) / p * psum % MOD;
        j--;
    }
    total %= MOD;

    // cout << "range " << n << " " << i << " " << j << " " << q << endl;
    int64_t cnt = (j - i + 1) / p;
    total += cnt * (cnt - 1) / 2 % MOD * psum % MOD;
    total += cnt * maxpath[i] % MOD;
    total %= MOD;
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        dist[i] = -INF;
    dist[0] = 0;
    for (int k = 1; k <= 3 * n; k++) {
        vector <int64_t> d(n, -INF);
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[e.first] = max(d[e.first], dist[i] + e.second);
        for (int i = 0; i < n; i++) {
            dist[i] = d[i];
            maxpath[k] = max(maxpath[k], d[i]);
        }
        // cout << k << " " << maxpath[k] << endl;
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t dist[MAXN];
int64_t maxpath[MAXN];

bool check_period(int len) {
    int64_t diff = maxpath[n + len] - maxpath[n];
    for (int i = 0; i < n; i++)
        if (maxpath[n + len + i] - maxpath[n + i] != diff)
            return false;
    return true;
}

int64_t solve() {
    if (q <= 3 * n) {
        int64_t total = 0;
        for (int k = 1; k <= q; k++)
            total += maxpath[k];
        total %= MOD;
        return total;
    }
    int p = 1;
    while (!check_period(p))
        p++;

    int64_t total = 0;
    for (int k = 1; k < n; k++)
        total += maxpath[k];
    int64_t psum = 0;
    for (int k = n; k < n + p; k++)
        psum += maxpath[k + p] - maxpath[k];
    // cout << "period " << p << " " << psum << endl;

    int i = n;
    while (i % p != 0) {
        total += maxpath[i];
        i++;
    }
    int j = q;
    while (j % p != p - 1) {
        total += maxpath[j];
        j--;
    }
    // cout << "range " << n << " " << i << " " << j << " " << q << endl;
    int64_t cnt = (j - i + 1) / p;
    total += cnt * (cnt - 1) / 2 % MOD * psum % MOD;
    total += cnt * maxpath[i] % MOD;
    total %= MOD;
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        dist[i] = -INF;
    dist[0] = 0;
    for (int k = 1; k <= 3 * n; k++) {
        vector <int64_t> d(n, -INF);
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[e.first] = max(d[e.first], dist[i] + e.second);
        for (int i = 0; i < n; i++) {
            dist[i] = d[i];
            maxpath[k] = max(maxpath[k], d[i]);
        }
        // cout << k << " " << maxpath[k] << endl;
    }

    cout << solve() << endl;
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

constexpr static int MOD = 1e9 + 7;
constexpr static int MAXN = 2048;
constexpr static int64_t INF = 1e18;

int n, m, q;

vector <pair <int, int>> adj[MAXN];
int64_t dist[MAXN];
int64_t maxpath[MAXN];

bool check_period(int len) {
    int64_t diff = maxpath[n + len] - maxpath[n];
    for (int i = 0; i < n; i++)
        if (maxpath[n + len + i] - maxpath[n + i] != diff)
            return false;
    return true;
}

int64_t solve() {
    if (q <= 3 * n) {
        int64_t total = 0;
        for (int k = 1; k <= q; k++)
            total += maxpath[k];
        total %= MOD;
        return total;
    }
    int p = 1;
    while (!check_period(p))
        p++;

    int64_t total = 0;
    for (int k = 1; k < n; k++)
        total += maxpath[k];
    int64_t psum = 0;
    for (int k = n; k < n + p; k++)
        psum += maxpath[k + p] - maxpath[k];
    // cout << "period " << p << " " << psum << endl;

    int i = n;
    while (i % p != (q + 1) % p) {
        total += maxpath[i];
        i++;
    }
    total %= MOD;

    // cout << "range " << n << " " << i << " " << q << endl;
    int64_t cnt = (q - i + 1) / p;
    total += cnt * (cnt - 1) / 2 % MOD * psum % MOD;
    total += cnt * maxpath[i] % MOD;
    total %= MOD;
    return total;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    for (int i = 0; i < n; i++)
        dist[i] = -INF;
    dist[0] = 0;
    for (int k = 1; k <= 3 * n; k++) {
        vector <int64_t> d(n, -INF);
        for (int i = 0; i < n; i++)
            for (auto e : adj[i])
                d[e.first] = max(d[e.first], dist[i] + e.second);
        for (int i = 0; i < n; i++) {
            dist[i] = d[i];
            maxpath[k] = max(maxpath[k], d[i]);
        }
        // cout << k << " " << maxpath[k] << endl;
    }

    cout << solve() << endl;
}


#include <iostream>
#include <fstream>
#include <algorithm>
#include <functional>
#include <array>
#include <chrono>
#include <random>
#include <vector>
#include <string>
#include <cmath>
#include <bitset>
#include <list>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cassert>

#define sq(x) ((x) * (x))
#define err(x) cerr << "["#x"]  " << (x) << "\n";
#define errp(x) cerr << "["#x"]  {" << ((x).first) << ", " << ((x).second) << "}\n";
#define errv(x) {cerr << "["#x"]  [";for(const auto& ___ : (x)) cerr << ___ << ", "; cerr << "]\n";}
#define errvn(x, n) {cerr << "["#x"]  [";for(auto ___ = 0; ___ < (n); ++___) cerr << (x)[___] << ", "; cerr << "]\n";}
#define errf() cerr << "\n\n";

//#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast, unroll-loops", "omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native,avx2")

using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

ll getrnd(ll l, ll r) {
    return uniform_int_distribution<ll>(l, r)(rng);
}

template <typename T1, typename T2>
inline bool relax(T1& a, const T2& b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}

template <typename T1, typename T2>
inline bool strain(T1& a, const T2& b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}

// :::::::::::::::::::::::::::::::

const int MOD = 1e9 + 7;

int add(int a, int b) {
    a += b;
    if (a >= MOD) a -= MOD;
    if (a < 0) a += MOD;
    return a;
}

int mul(int a, int b) {
    return 1LL * a * b % MOD;
}

int binpow(int a, ll n) {
    if (n < 0)
        a = binpow(a, MOD - 2), n *= -1;

    int res = 1;
    while (n) {
        if (n & 1)
            res = mul(res, a);
        a = mul(a, a);
        n /= 2;
    }
    return res;
}

int inv(int x) {
    return binpow(x, MOD - 2);
}

struct line {
    ll k, c;

    line () {}
    line (ll x, ll y) : k(x), c(y) {}

    ll eval(ll x) {
        return k * x + c;
    }
    ld inter(const line& x) {
        return (ld)(x.c - c) / (k - x.k);
    }
    ll interRound(const line& x) {
        return (x.c - c) / (k - x.k);
    }
};

void solve() {
    int n, m, q;
    cin >> n >> m >> q;

    vector<tuple<int, int, int>> edges, nodub;
    for (int i = 0; i < m; ++i) {
        int x, y, w;
        cin >> x >> y >> w;
        --x; --y;

        edges.emplace_back(x, y, w);
        nodub.emplace_back(x, y, w);
        edges.emplace_back(y, x, w);
    }

    int ans = 0;
    vector<ll> dl(n, -1), sdw(n), dw(n, -1e17);
    dw[0] = dl[0] = sdw[0] = 0;
    for (int i = 0; i < m; ++i) {
        vector<ll> ndw(n, -1e17);
        for (const auto& [x, y, w] : edges)
            strain(ndw[y], dw[x] + w);
        ndw.swap(dw);
        for (int j = 0; j < n; ++j)
            if (dl[j] == -1 && dw[j] > 0)
                dl[j] = i + 1, sdw[j] = dw[j];
        ans = add(ans, (*max_element(dw.begin(), dw.end())) % MOD);
    }
//    sdw.swap(dw);
//    errv(sdw);
//    errv(dl);

    // now all len from 1..m computed
    if (q == m) {
        cout << ans << '\n';
        return;
    }

    vector<line> lines;
//    for (auto [x, y, w] : nodub) {
//        if (dl[x] > dl[y] || (dl[x] == dl[y] && dw[x] < dw[y]))
//            swap(x, y);
//
//        lines.emplace_back(w, dw[x] - 1LL * w * dl[x]);
//    }
    vector<int> mxfrom(n, -1);
    for (auto [x, y, w] : edges)
        strain(mxfrom[x], w);
    for (int i = 0; i < n; ++i) {
        lines.emplace_back(mxfrom[i], -1LL * mxfrom[i] * m + dw[i]);
    }

    sort(lines.begin(), lines.end(), [](const line& a, const line& b) {
        return a.k < b.k || (a.k == b.k && a.c > b.c);
    });

//    for (int i = 0; i < lines.size(); ++i)
//        cout << lines[i].k << ' ' << lines[i].c << '\n';
//    errf();

    ll lstk = -1e17;
    deque<line> hull;
    for (const line& x : lines) {
        if (x.k == lstk) continue;

        while (hull.size() >= 2 && hull[hull.size() - 1].inter(x) <= hull[hull.size() - 1].inter(hull[hull.size() - 2]))
            hull.pop_back();
        hull.push_back(x);
        lstk = x.k;
    }

    vector<line> a(hull.begin(), hull.end());
//    for (int i = 0; i < a.size(); ++i)
//        cout << a[i].k << ' ' << a[i].c << '\n';
    int st = 0, en = 0;
//    while (st + 1 < a.size() && a[st].eval(m + 1) <= a[st + 1].eval(m + 1))
//        ++st;
//    while (en + 1 < a.size() && a[en].eval(q) <= a[en + 1].eval(q))
//        ++en;
    while (st + 1 < a.size() && a[st].inter(a[st + 1]) < m + 1)
        ++st;
    while (en + 1 < a.size() && a[en].inter(a[en + 1]) < q)
        ++en;

    vector<pair<ll, ll>> border;
    if (st != en) {
        border.emplace_back(m + 1, (ll)a[st].interRound(a[st + 1]));
        for (int i = st + 1; i < en; ++i) {
            ll l = border.back().second + 1;
            ll r = (ll)a[i].interRound(a[i + 1]);

            border.emplace_back(l, r);
        }
        if (border.back().second + 1 <= q)
            border.emplace_back(border.back().second + 1, q);
    }
    else
        border.emplace_back(m + 1, q);

    for (int i = 0; i < border.size(); ++i)
        relax(border[i].second, q), relax(border[i].first, border[i].second);

//    err(ans);
    int div2 = inv(2);
    for (int i = 0; i < border.size(); ++i) {
        auto [l, r] = border[i];
        if (l > r) continue;

        ll len = r - l;
        ll f = a[st + i].eval(l);
//        ll s = f * (len + 1) + a[st + i].k * (len + 1) * len / 2;

        int w = a[st + i].k % MOD;
        int mlen = len % MOD;
        int mf = f % MOD;

        ll s = add(mul(mf, mlen + 1), mul(w, mul(mlen, mul(div2, mlen + 1))));
//        ll s = 0;
//        for (int j = l; j <= r; ++j)
//            s += a[st + i].eval(j);
        ans = add(ans, s);
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(nullptr); cout.tie(nullptr);
    srand(time(0));

    int t = 1;
//    cin >> t;
    while (t--)
        solve();

    return 0;
}


#include <iostream>
#include <fstream>
#include <algorithm>
#include <functional>
#include <array>
#include <chrono>
#include <random>
#include <vector>
#include <string>
#include <cmath>
#include <bitset>
#include <list>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cassert>

#define sq(x) ((x) * (x))
#define err(x) cerr << "["#x"]  " << (x) << "\n";
#define errp(x) cerr << "["#x"]  {" << ((x).first) << ", " << ((x).second) << "}\n";
#define errv(x) {cerr << "["#x"]  [";for(const auto& ___ : (x)) cerr << ___ << ", "; cerr << "]\n";}
#define errvn(x, n) {cerr << "["#x"]  [";for(auto ___ = 0; ___ < (n); ++___) cerr << (x)[___] << ", "; cerr << "]\n";}
#define errf() cerr << "\n\n";

//#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast, unroll-loops", "omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native,avx2")

using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

ll getrnd(ll l, ll r) {
    return uniform_int_distribution<ll>(l, r)(rng);
}

template <typename T1, typename T2>
inline bool relax(T1& a, const T2& b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}

template <typename T1, typename T2>
inline bool strain(T1& a, const T2& b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}

// :::::::::::::::::::::::::::::::

const int MOD = 1e9 + 7;

int add(int a, int b) {
    a += b;
    if (a >= MOD) a -= MOD;
    if (a < 0) a += MOD;
    return a;
}

int mul(int a, int b) {
    return 1LL * a * b % MOD;
}

int binpow(int a, ll n) {
    if (n < 0)
        a = binpow(a, MOD - 2), n *= -1;

    int res = 1;
    while (n) {
        if (n & 1)
            res = mul(res, a);
        a = mul(a, a);
        n /= 2;
    }
    return res;
}

int inv(int x) {
    return binpow(x, MOD - 2);
}

struct line {
    ll k, c;

    line () {}
    line (ll x, ll y) : k(x), c(y) {}

    ll eval(ll x) {
        return k * x + c;
    }
    ld inter(const line& x) {
        return (ld)(x.c - c) / (k - x.k);
    }
    ll interRound(const line& x) {
        return (x.c - c) / (k - x.k);
    }
};

void solve() {
    int n, m, q;
    cin >> n >> m >> q;

    vector<tuple<int, int, int>> edges, nodub;
    for (int i = 0; i < m; ++i) {
        int x, y, w;
        cin >> x >> y >> w;
        --x; --y;

        edges.emplace_back(x, y, w);
        nodub.emplace_back(x, y, w);
        edges.emplace_back(y, x, w);
    }

    int ans = 0;
    vector<ll> dl(n, -1), sdw(n), dw(n, -1e17);
    dw[0] = dl[0] = sdw[0] = 0;
    for (int i = 0; i < m; ++i) {
        vector<ll> ndw(n, -1e17);
        for (const auto& [x, y, w] : edges)
            strain(ndw[y], dw[x] + w);
        ndw.swap(dw);
        for (int j = 0; j < n; ++j)
            if (dl[j] == -1 && dw[j] > 0)
                dl[j] = i + 1, sdw[j] = dw[j];
        ans = add(ans, (*max_element(dw.begin(), dw.end())) % MOD);
    }
    sdw.swap(dw);
//    errv(sdw);
//    errv(dl);

    // now all len from 1..m computed
    if (q == m) {
        cout << ans << '\n';
        return;
    }

    vector<line> lines;
    for (auto [x, y, w] : nodub) {
        if (dl[x] > dl[y] || (dl[x] == dl[y] && dw[x] < dw[y]))
            swap(x, y);

        lines.emplace_back(w, dw[x] - 1LL * w * dl[x]);
    }
    sort(lines.begin(), lines.end(), [](const line& a, const line& b) {
        return a.k < b.k || (a.k == b.k && a.c > b.c);
    });

//    for (int i = 0; i < lines.size(); ++i)
//        cout << lines[i].k << ' ' << lines[i].c << '\n';
//    errf();

    ll lstk = -1e17;
    deque<line> hull;
    for (const line& x : lines) {
        if (x.k == lstk) continue;

        while (hull.size() >= 2 && hull[hull.size() - 1].inter(x) <= hull[hull.size() - 1].inter(hull[hull.size() - 2]))
            hull.pop_back();
        hull.push_back(x);
        lstk = x.k;
    }

    vector<line> a(hull.begin(), hull.end());
//    for (int i = 0; i < a.size(); ++i)
//        cout << a[i].k << ' ' << a[i].c << '\n';
    int st = 0, en = 0;
    while (st + 1 < a.size() && a[st].eval(m + 1) <= a[st + 1].eval(m + 1))
        ++st;
    while (en + 1 < a.size() && a[en].eval(q) <= a[en + 1].eval(q))
        ++en;

    vector<pair<ll, ll>> border;
    if (st != en) {
        border.emplace_back(m + 1, (ll)a[st].interRound(a[st + 1]));
        for (int i = st + 1; i < en; ++i) {
            ll l = border.back().second + 1;
            ll r = (ll)a[i].interRound(a[i + 1]);

            border.emplace_back(l, r);
        }
        if (border.back().second + 1 <= q)
            border.emplace_back(border.back().second + 1, q);
    }
    else
        border.emplace_back(m + 1, q);

    for (int i = 0; i < border.size(); ++i)
        relax(border[i].second, q);

//    err(ans);
    for (int i = 0; i < border.size(); ++i) {
        auto [l, r] = border[i];
        ll len = r - l;
        ll f = a[st + i].eval(l);
//        ll s = f * (len + 1) + a[st + i].k * (len + 1) * len / 2;
        ll s = add(f * (len + 1) % MOD, mul(a[st + i].k % MOD, ((len + 1) * len / 2) % MOD));
//        ll s = 0;
//        for (int j = l; j <= r; ++j)
//            s += a[st + i].eval(j);
        ans = add(ans, s);
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(nullptr); cout.tie(nullptr);
    srand(time(0));

    int t = 1;
//    cin >> t;
    while (t--)
        solve();

    return 0;
}