#include <iostream>
#include <cstdio>
#include <fstream>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <functional>
#include <numeric>
#include <cstdlib>
#include <iomanip>
#include <cassert>
using namespace std;
const int MAXN = 200005;
const int LOG = 18;
int center, timer, n, m, l, x, y, t, edgesInPath, furthestNode, diameterNode1, diameterNode2;
long long maxDist;
int timeIn[MAXN];
int timeOut[MAXN];
int up[MAXN][19];
bool visited[MAXN];
int edgesFromRoot[MAXN];
long long distanceFromRoot[MAXN];
vector<pair<int, int> > graph[MAXN];
long long componentDiameter, centerFar;
void dfsInit(int v, int parent, int pathEdges, long long pathLength) {
visited[v] = true;
up[v][0] = parent;
distanceFromRoot[v] = pathLength;
edgesFromRoot[v] = pathEdges;
timeIn[v] = ++timer;
for (int i = 1; i <= LOG; i++) {
up[v][i] = up[up[v][i - 1]][i - 1];
}
for (int i = 0; i < (int)graph[v].size(); i++) {
int to = graph[v][i].first;
int len = graph[v][i].second;
if (to != parent) {
dfsInit(to, v, pathEdges + 1, pathLength + len);
}
}
timeOut[v] = ++timer;
}
void dfsDiameter(int v, int parent, int pathEdges, long long pathLength) {
if (pathLength > maxDist) {
maxDist = pathLength;
furthestNode = v;
edgesInPath = pathEdges;
}
for (int i = 0; i < (int)graph[v].size(); i++) {
int to = graph[v][i].first;
int len = graph[v][i].second;
if (to != parent) {
dfsDiameter(to, v, pathEdges + 1, pathLength + len);
}
}
}
struct component {
long long diameter;
int center;
long long centerFar;
component() {}
component(long long _diameter, int _center, long long _centerFar): diameter(_diameter), center(_center), centerFar(_centerFar) {}
};
inline bool operator < (const component & a, const component & b) {
return (a.diameter > b.diameter || (a.diameter == b.diameter && a.center < b.center));
}
vector<component> initialComponents;
multiset<component> forest;
multiset<component>::iterator it;
component componentA, componentB;
bool isAncestor(int x, int y) {
return (timeIn[x] <= timeIn[y] && timeOut[x] >= timeOut[y]);
}
int findLCA(int a, int b) {
if (isAncestor(a, b)) {
return a;
}
if (isAncestor(b, a)) {
return b;
}
for (int i = LOG; i >= 0; i--) {
if (!isAncestor(up[a][i], b)) {
a = up[a][i];
}
}
return up[a][0];
}
long long distanceBetween(int a, int b) {
return distanceFromRoot[a] + distanceFromRoot[b] - 2 * distanceFromRoot[findLCA(a, b)];
}
int edgesBetween(int a, int b) {
return edgesFromRoot[a] + edgesFromRoot[b] - 2 * edgesFromRoot[findLCA(a, b)];
}
int getUp(int v, int jump) {
for (int i = 0; i <= LOG; i++) {
if (jump & (1 << i)) {
v = up[v][i];
}
}
return v;
}
int pathDive(int pathNode1, int pathNode2, int edgesInPath, int dive) {
int LCA = findLCA(pathNode1, pathNode2);
int jump = min(dive, edgesFromRoot[pathNode1] - edgesFromRoot[LCA]);
dive -= jump;
if (dive > 0) {
return getUp(pathNode2, edgesFromRoot[pathNode2] - edgesFromRoot[LCA] - dive);
} else {
return getUp(pathNode1, jump);
}
}
int findCenter(int pathNode1, int pathNode2, int edgesInPath) {
int l, r, mid, iter, pathNode, bestCenter;
long long f1, f2, bestF;
bestF = (long long)9e18;
l = 0; r = edgesInPath;
for (iter = 0; iter < LOG; iter++) {
mid = (l + r) >> 1;
pathNode = pathDive(pathNode1, pathNode2, edgesInPath, mid);
f1 = max(distanceBetween(pathNode, pathNode1), distanceBetween(pathNode, pathNode2));
if (f1 < bestF) {
bestF = f1;
bestCenter = pathNode;
}
if (mid < edgesInPath) {
pathNode = pathDive(pathNode1, pathNode2, edgesInPath, mid + 1);
f2 = max(distanceBetween(pathNode, pathNode1), distanceBetween(pathNode, pathNode2));
if (f2 < bestF) {
bestF = f2;
bestCenter = pathNode;
}
if (f1 < f2) {
r = mid;
} else {
l = mid;
}
}
}
for (int goBack = 1; goBack <= 4; goBack++) {
if (edgesBetween(pathNode1, bestCenter) < goBack) {
break;
}
int attempt = pathDive(bestCenter, pathNode1, edgesBetween(pathNode1, bestCenter), goBack);
f1 = max(distanceBetween(pathNode1, attempt), distanceBetween(pathNode2, attempt));
if (f1 < bestF) {
bestF = f1;
bestCenter = attempt;
}
}
for (int goForward = 1; goForward <= 4; goForward++) {
if (edgesBetween(bestCenter, pathNode2) < goForward) {
break;
}
int attempt = pathDive(bestCenter, pathNode2, edgesBetween(bestCenter, pathNode2), goForward);
f1 = max(distanceBetween(pathNode1, attempt), distanceBetween(pathNode2, attempt));
if (f1 < bestF) {
bestF = f1;
bestCenter = attempt;
}
}
return bestCenter;
}
component mergeComponents(component a, component b) {
int aCenter = a.center;
int bCenter = b.center;
long long aFar = a.centerFar;
long long bFar = b.centerFar;
long long cDiameter = aFar + l + bFar;
int cCenter;
long long cCenterFar;
if (aFar <= bFar) {
cCenter = bCenter;
cCenterFar = max(aFar + l, bFar);
} else {
cCenter = aCenter;
cCenterFar = max(aFar, bFar + l);
}
if (cDiameter < a.diameter) {
cDiameter = a.diameter;
cCenter = a.center;
cCenterFar = a.centerFar;
}
if (cDiameter < b.diameter) {
cDiameter = b.diameter;
cCenter = b.center;
cCenterFar = b.centerFar;
}
return component(cDiameter, cCenter, cCenterFar);
}
int main() {
//freopen("input.txt", "r", stdin);
scanf("%d %d %d", &n, &m, &l);
for (int i = 0; i < m; i++) {
scanf("%d %d %d", &x, &y, &t);
graph[x].push_back(make_pair(y, t));
graph[y].push_back(make_pair(x, t));
}
for (int i = 0; i < n; i++) {
if (visited[i]) {
continue;
}
dfsInit(i, i, 0, 0);
maxDist = furthestNode = -1;
dfsDiameter(i, i, 0, 0);
diameterNode1 = furthestNode;
maxDist = furthestNode = -1;
dfsDiameter(diameterNode1, diameterNode1, 0, 0);
diameterNode2 = furthestNode;
assert(diameterNode1 != -1 && diameterNode2 != -1);
center = findCenter(diameterNode1, diameterNode2, edgesInPath);
componentDiameter = maxDist;
centerFar = max(distanceBetween(diameterNode1, center), distanceBetween(diameterNode2, center));
initialComponents.push_back(component(componentDiameter, center, centerFar));
}
sort(initialComponents.begin(), initialComponents.end());
component ans = initialComponents[0];
for (int i = 1; i < (int)initialComponents.size(); i++) {
ans = mergeComponents(ans, initialComponents[i]);
}
cout << ans.diameter << "\n";
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y3N0ZGlvPgojaW5jbHVkZSA8ZnN0cmVhbT4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPGNzdHJpbmc+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxzdGFjaz4KI2luY2x1ZGUgPHF1ZXVlPgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8c2V0PgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KI2luY2x1ZGUgPG51bWVyaWM+CiNpbmNsdWRlIDxjc3RkbGliPgojaW5jbHVkZSA8aW9tYW5pcD4KI2luY2x1ZGUgPGNhc3NlcnQ+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKY29uc3QgaW50IE1BWE4gPSAyMDAwMDU7CmNvbnN0IGludCBMT0cgPSAxODsKCmludCBjZW50ZXIsIHRpbWVyLCBuLCBtLCBsLCB4LCB5LCB0LCBlZGdlc0luUGF0aCwgZnVydGhlc3ROb2RlLCBkaWFtZXRlck5vZGUxLCBkaWFtZXRlck5vZGUyOwpsb25nIGxvbmcgbWF4RGlzdDsKaW50IHRpbWVJbltNQVhOXTsKaW50IHRpbWVPdXRbTUFYTl07CmludCB1cFtNQVhOXVsxOV07CmJvb2wgdmlzaXRlZFtNQVhOXTsKaW50IGVkZ2VzRnJvbVJvb3RbTUFYTl07CmxvbmcgbG9uZyBkaXN0YW5jZUZyb21Sb290W01BWE5dOwp2ZWN0b3I8cGFpcjxpbnQsIGludD4gPiBncmFwaFtNQVhOXTsKbG9uZyBsb25nIGNvbXBvbmVudERpYW1ldGVyLCBjZW50ZXJGYXI7Cgp2b2lkIGRmc0luaXQoaW50IHYsIGludCBwYXJlbnQsIGludCBwYXRoRWRnZXMsIGxvbmcgbG9uZyBwYXRoTGVuZ3RoKSB7Cgl2aXNpdGVkW3ZdID0gdHJ1ZTsKCXVwW3ZdWzBdID0gcGFyZW50OwoJZGlzdGFuY2VGcm9tUm9vdFt2XSA9IHBhdGhMZW5ndGg7CgllZGdlc0Zyb21Sb290W3ZdID0gcGF0aEVkZ2VzOwoJdGltZUluW3ZdID0gKyt0aW1lcjsKCWZvciAoaW50IGkgPSAxOyBpIDw9IExPRzsgaSsrKSB7CgkJdXBbdl1baV0gPSB1cFt1cFt2XVtpIC0gMV1dW2kgLSAxXTsKCX0KCWZvciAoaW50IGkgPSAwOyBpIDwgKGludClncmFwaFt2XS5zaXplKCk7IGkrKykgewoJCWludCB0byA9IGdyYXBoW3ZdW2ldLmZpcnN0OwoJCWludCBsZW4gPSBncmFwaFt2XVtpXS5zZWNvbmQ7CgkJaWYgKHRvICE9IHBhcmVudCkgewoJCQlkZnNJbml0KHRvLCB2LCBwYXRoRWRnZXMgKyAxLCBwYXRoTGVuZ3RoICsgbGVuKTsKCQl9Cgl9Cgl0aW1lT3V0W3ZdID0gKyt0aW1lcjsKfQoKdm9pZCBkZnNEaWFtZXRlcihpbnQgdiwgaW50IHBhcmVudCwgaW50IHBhdGhFZGdlcywgbG9uZyBsb25nIHBhdGhMZW5ndGgpIHsKCWlmIChwYXRoTGVuZ3RoID4gbWF4RGlzdCkgewoJCW1heERpc3QgPSBwYXRoTGVuZ3RoOwoJCWZ1cnRoZXN0Tm9kZSA9IHY7CgkJZWRnZXNJblBhdGggPSBwYXRoRWRnZXM7Cgl9Cglmb3IgKGludCBpID0gMDsgaSA8IChpbnQpZ3JhcGhbdl0uc2l6ZSgpOyBpKyspIHsKCQlpbnQgdG8gPSBncmFwaFt2XVtpXS5maXJzdDsKCQlpbnQgbGVuID0gZ3JhcGhbdl1baV0uc2Vjb25kOwoJCWlmICh0byAhPSBwYXJlbnQpIHsKCQkJZGZzRGlhbWV0ZXIodG8sIHYsIHBhdGhFZGdlcyArIDEsIHBhdGhMZW5ndGggKyBsZW4pOwoJCX0KCX0KfQoKc3RydWN0IGNvbXBvbmVudCB7Cglsb25nIGxvbmcgZGlhbWV0ZXI7CglpbnQgY2VudGVyOwoJbG9uZyBsb25nIGNlbnRlckZhcjsKCWNvbXBvbmVudCgpIHt9Cgljb21wb25lbnQobG9uZyBsb25nIF9kaWFtZXRlciwgaW50IF9jZW50ZXIsIGxvbmcgbG9uZyBfY2VudGVyRmFyKTogZGlhbWV0ZXIoX2RpYW1ldGVyKSwgY2VudGVyKF9jZW50ZXIpLCBjZW50ZXJGYXIoX2NlbnRlckZhcikge30KfTsKCmlubGluZSBib29sIG9wZXJhdG9yIDwgKGNvbnN0IGNvbXBvbmVudCAmIGEsIGNvbnN0IGNvbXBvbmVudCAmIGIpIHsKCXJldHVybiAoYS5kaWFtZXRlciA+IGIuZGlhbWV0ZXIgfHwgKGEuZGlhbWV0ZXIgPT0gYi5kaWFtZXRlciAmJiBhLmNlbnRlciA8IGIuY2VudGVyKSk7Cn0KCnZlY3Rvcjxjb21wb25lbnQ+IGluaXRpYWxDb21wb25lbnRzOwptdWx0aXNldDxjb21wb25lbnQ+IGZvcmVzdDsKbXVsdGlzZXQ8Y29tcG9uZW50Pjo6aXRlcmF0b3IgaXQ7CmNvbXBvbmVudCBjb21wb25lbnRBLCBjb21wb25lbnRCOwoKYm9vbCBpc0FuY2VzdG9yKGludCB4LCBpbnQgeSkgewoJcmV0dXJuICh0aW1lSW5beF0gPD0gdGltZUluW3ldICYmIHRpbWVPdXRbeF0gPj0gdGltZU91dFt5XSk7Cn0KCmludCBmaW5kTENBKGludCBhLCBpbnQgYikgewoJaWYgKGlzQW5jZXN0b3IoYSwgYikpIHsKCQlyZXR1cm4gYTsKCX0KCWlmIChpc0FuY2VzdG9yKGIsIGEpKSB7CgkJcmV0dXJuIGI7Cgl9Cglmb3IgKGludCBpID0gTE9HOyBpID49IDA7IGktLSkgewoJCWlmICghaXNBbmNlc3Rvcih1cFthXVtpXSwgYikpIHsKCQkJYSA9IHVwW2FdW2ldOwoJCX0KCX0KCXJldHVybiB1cFthXVswXTsKfQoKbG9uZyBsb25nIGRpc3RhbmNlQmV0d2VlbihpbnQgYSwgaW50IGIpIHsKCXJldHVybiBkaXN0YW5jZUZyb21Sb290W2FdICsgZGlzdGFuY2VGcm9tUm9vdFtiXSAtIDIgKiBkaXN0YW5jZUZyb21Sb290W2ZpbmRMQ0EoYSwgYildOwp9CgppbnQgZWRnZXNCZXR3ZWVuKGludCBhLCBpbnQgYikgewoJcmV0dXJuIGVkZ2VzRnJvbVJvb3RbYV0gKyBlZGdlc0Zyb21Sb290W2JdIC0gMiAqIGVkZ2VzRnJvbVJvb3RbZmluZExDQShhLCBiKV07Cn0KCmludCBnZXRVcChpbnQgdiwgaW50IGp1bXApIHsKCWZvciAoaW50IGkgPSAwOyBpIDw9IExPRzsgaSsrKSB7CgkJaWYgKGp1bXAgJiAoMSA8PCBpKSkgewoJCQl2ID0gdXBbdl1baV07CgkJfQoJfQoJcmV0dXJuIHY7Cn0KCmludCBwYXRoRGl2ZShpbnQgcGF0aE5vZGUxLCBpbnQgcGF0aE5vZGUyLCBpbnQgZWRnZXNJblBhdGgsIGludCBkaXZlKSB7CglpbnQgTENBID0gZmluZExDQShwYXRoTm9kZTEsIHBhdGhOb2RlMik7CglpbnQganVtcCA9IG1pbihkaXZlLCBlZGdlc0Zyb21Sb290W3BhdGhOb2RlMV0gLSBlZGdlc0Zyb21Sb290W0xDQV0pOwoJZGl2ZSAtPSBqdW1wOwoJaWYgKGRpdmUgPiAwKSB7CgkJcmV0dXJuIGdldFVwKHBhdGhOb2RlMiwgZWRnZXNGcm9tUm9vdFtwYXRoTm9kZTJdIC0gZWRnZXNGcm9tUm9vdFtMQ0FdIC0gZGl2ZSk7Cgl9IGVsc2UgewoJCXJldHVybiBnZXRVcChwYXRoTm9kZTEsIGp1bXApOwoJfQp9CgppbnQgZmluZENlbnRlcihpbnQgcGF0aE5vZGUxLCBpbnQgcGF0aE5vZGUyLCBpbnQgZWRnZXNJblBhdGgpIHsKCWludCBsLCByLCBtaWQsIGl0ZXIsIHBhdGhOb2RlLCBiZXN0Q2VudGVyOwoJbG9uZyBsb25nIGYxLCBmMiwgYmVzdEY7CgliZXN0RiA9IChsb25nIGxvbmcpOWUxODsKCWwgPSAwOyByID0gZWRnZXNJblBhdGg7Cglmb3IgKGl0ZXIgPSAwOyBpdGVyIDwgTE9HOyBpdGVyKyspIHsKCQltaWQgPSAobCArIHIpID4+IDE7CgkJcGF0aE5vZGUgPSBwYXRoRGl2ZShwYXRoTm9kZTEsIHBhdGhOb2RlMiwgZWRnZXNJblBhdGgsIG1pZCk7CgkJZjEgPSBtYXgoZGlzdGFuY2VCZXR3ZWVuKHBhdGhOb2RlLCBwYXRoTm9kZTEpLCBkaXN0YW5jZUJldHdlZW4ocGF0aE5vZGUsIHBhdGhOb2RlMikpOwoJCWlmIChmMSA8IGJlc3RGKSB7CgkJCWJlc3RGID0gZjE7CgkJCWJlc3RDZW50ZXIgPSBwYXRoTm9kZTsKCQl9CgkJaWYgKG1pZCA8IGVkZ2VzSW5QYXRoKSB7CgkJCXBhdGhOb2RlID0gcGF0aERpdmUocGF0aE5vZGUxLCBwYXRoTm9kZTIsIGVkZ2VzSW5QYXRoLCBtaWQgKyAxKTsKCQkJZjIgPSBtYXgoZGlzdGFuY2VCZXR3ZWVuKHBhdGhOb2RlLCBwYXRoTm9kZTEpLCBkaXN0YW5jZUJldHdlZW4ocGF0aE5vZGUsIHBhdGhOb2RlMikpOwoJCQlpZiAoZjIgPCBiZXN0RikgewoJCQkJYmVzdEYgPSBmMjsKCQkJCWJlc3RDZW50ZXIgPSBwYXRoTm9kZTsKCQkJfQoJCQlpZiAoZjEgPCBmMikgewoJCQkJciA9IG1pZDsKCQkJfSBlbHNlIHsKCQkJCWwgPSBtaWQ7CgkJCX0KCQl9Cgl9Cglmb3IgKGludCBnb0JhY2sgPSAxOyBnb0JhY2sgPD0gNDsgZ29CYWNrKyspIHsKCQlpZiAoZWRnZXNCZXR3ZWVuKHBhdGhOb2RlMSwgYmVzdENlbnRlcikgPCBnb0JhY2spIHsKCQkJYnJlYWs7CgkJfQoJCWludCBhdHRlbXB0ID0gcGF0aERpdmUoYmVzdENlbnRlciwgcGF0aE5vZGUxLCBlZGdlc0JldHdlZW4ocGF0aE5vZGUxLCBiZXN0Q2VudGVyKSwgZ29CYWNrKTsKCQlmMSA9IG1heChkaXN0YW5jZUJldHdlZW4ocGF0aE5vZGUxLCBhdHRlbXB0KSwgZGlzdGFuY2VCZXR3ZWVuKHBhdGhOb2RlMiwgYXR0ZW1wdCkpOwoJCWlmIChmMSA8IGJlc3RGKSB7CgkJCWJlc3RGID0gZjE7CgkJCWJlc3RDZW50ZXIgPSBhdHRlbXB0OwoJCX0KCX0KCWZvciAoaW50IGdvRm9yd2FyZCA9IDE7IGdvRm9yd2FyZCA8PSA0OyBnb0ZvcndhcmQrKykgewoJCWlmIChlZGdlc0JldHdlZW4oYmVzdENlbnRlciwgcGF0aE5vZGUyKSA8IGdvRm9yd2FyZCkgewoJCQlicmVhazsKCQl9CgkJaW50IGF0dGVtcHQgPSBwYXRoRGl2ZShiZXN0Q2VudGVyLCBwYXRoTm9kZTIsIGVkZ2VzQmV0d2VlbihiZXN0Q2VudGVyLCBwYXRoTm9kZTIpLCBnb0ZvcndhcmQpOwoJCWYxID0gbWF4KGRpc3RhbmNlQmV0d2VlbihwYXRoTm9kZTEsIGF0dGVtcHQpLCBkaXN0YW5jZUJldHdlZW4ocGF0aE5vZGUyLCBhdHRlbXB0KSk7CgkJaWYgKGYxIDwgYmVzdEYpIHsKCQkJYmVzdEYgPSBmMTsKCQkJYmVzdENlbnRlciA9IGF0dGVtcHQ7CgkJfQoJfQoJcmV0dXJuIGJlc3RDZW50ZXI7Cn0KCmNvbXBvbmVudCBtZXJnZUNvbXBvbmVudHMoY29tcG9uZW50IGEsIGNvbXBvbmVudCBiKSB7CglpbnQgYUNlbnRlciA9IGEuY2VudGVyOwoJaW50IGJDZW50ZXIgPSBiLmNlbnRlcjsKCWxvbmcgbG9uZyBhRmFyID0gYS5jZW50ZXJGYXI7Cglsb25nIGxvbmcgYkZhciA9IGIuY2VudGVyRmFyOwoJbG9uZyBsb25nIGNEaWFtZXRlciA9IGFGYXIgKyBsICsgYkZhcjsKCWludCBjQ2VudGVyOwoJbG9uZyBsb25nIGNDZW50ZXJGYXI7CglpZiAoYUZhciA8PSBiRmFyKSB7CgkJY0NlbnRlciA9IGJDZW50ZXI7CgkJY0NlbnRlckZhciA9IG1heChhRmFyICsgbCwgYkZhcik7Cgl9IGVsc2UgewoJCWNDZW50ZXIgPSBhQ2VudGVyOwoJCWNDZW50ZXJGYXIgPSBtYXgoYUZhciwgYkZhciArIGwpOwoJfQoJaWYgKGNEaWFtZXRlciA8IGEuZGlhbWV0ZXIpIHsKCQljRGlhbWV0ZXIgPSBhLmRpYW1ldGVyOwoJCWNDZW50ZXIgPSBhLmNlbnRlcjsKCQljQ2VudGVyRmFyID0gYS5jZW50ZXJGYXI7Cgl9IAoJaWYgKGNEaWFtZXRlciA8IGIuZGlhbWV0ZXIpIHsKCQljRGlhbWV0ZXIgPSBiLmRpYW1ldGVyOwoJCWNDZW50ZXIgPSBiLmNlbnRlcjsKCQljQ2VudGVyRmFyID0gYi5jZW50ZXJGYXI7Cgl9CglyZXR1cm4gY29tcG9uZW50KGNEaWFtZXRlciwgY0NlbnRlciwgY0NlbnRlckZhcik7Cn0KCmludCBtYWluKCkgewoJLy9mcmVvcGVuKCJpbnB1dC50eHQiLCAiciIsIHN0ZGluKTsKCXNjYW5mKCIlZCAlZCAlZCIsICZuLCAmbSwgJmwpOwoJZm9yIChpbnQgaSA9IDA7IGkgPCBtOyBpKyspIHsKCQlzY2FuZigiJWQgJWQgJWQiLCAmeCwgJnksICZ0KTsKCQlncmFwaFt4XS5wdXNoX2JhY2sobWFrZV9wYWlyKHksIHQpKTsKCQlncmFwaFt5XS5wdXNoX2JhY2sobWFrZV9wYWlyKHgsIHQpKTsKCX0KCWZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CgkJaWYgKHZpc2l0ZWRbaV0pIHsKCQkJY29udGludWU7CgkJfQoJCWRmc0luaXQoaSwgaSwgMCwgMCk7CgkJbWF4RGlzdCA9IGZ1cnRoZXN0Tm9kZSA9IC0xOwoJCWRmc0RpYW1ldGVyKGksIGksIDAsIDApOwoJCWRpYW1ldGVyTm9kZTEgPSBmdXJ0aGVzdE5vZGU7CgkJbWF4RGlzdCA9IGZ1cnRoZXN0Tm9kZSA9IC0xOwoJCWRmc0RpYW1ldGVyKGRpYW1ldGVyTm9kZTEsIGRpYW1ldGVyTm9kZTEsIDAsIDApOwoJCWRpYW1ldGVyTm9kZTIgPSBmdXJ0aGVzdE5vZGU7CgkJYXNzZXJ0KGRpYW1ldGVyTm9kZTEgIT0gLTEgJiYgZGlhbWV0ZXJOb2RlMiAhPSAtMSk7CgkJY2VudGVyID0gZmluZENlbnRlcihkaWFtZXRlck5vZGUxLCBkaWFtZXRlck5vZGUyLCBlZGdlc0luUGF0aCk7CgkJY29tcG9uZW50RGlhbWV0ZXIgPSBtYXhEaXN0OwoJCWNlbnRlckZhciA9IG1heChkaXN0YW5jZUJldHdlZW4oZGlhbWV0ZXJOb2RlMSwgY2VudGVyKSwgZGlzdGFuY2VCZXR3ZWVuKGRpYW1ldGVyTm9kZTIsIGNlbnRlcikpOwoJCWluaXRpYWxDb21wb25lbnRzLnB1c2hfYmFjayhjb21wb25lbnQoY29tcG9uZW50RGlhbWV0ZXIsIGNlbnRlciwgY2VudGVyRmFyKSk7Cgl9Cglzb3J0KGluaXRpYWxDb21wb25lbnRzLmJlZ2luKCksIGluaXRpYWxDb21wb25lbnRzLmVuZCgpKTsKCWNvbXBvbmVudCBhbnMgPSBpbml0aWFsQ29tcG9uZW50c1swXTsKCWZvciAoaW50IGkgPSAxOyBpIDwgKGludClpbml0aWFsQ29tcG9uZW50cy5zaXplKCk7IGkrKykgewoJCWFucyA9IG1lcmdlQ29tcG9uZW50cyhhbnMsIGluaXRpYWxDb21wb25lbnRzW2ldKTsKCX0KCWNvdXQgPDwgYW5zLmRpYW1ldGVyIDw8ICJcbiI7CglyZXR1cm4gMDsKfQ==