#include #include #include #include #include #include using namespace std; const int MAXN = 100000 * 2 + 10; set > S; int f[MAXN], t[MAXN], p[MAXN], ii, wei[MAXN], par[MAXN], dist[MAXN], vn, n, wn, w[MAXN], s, m, x, y, z, k, a[MAXN], b[MAXN], c[MAXN], v[MAXN], d, choice, W, an, ax[MAXN], ay[MAXN]; bool used[MAXN]; vector > vec[MAXN]; void add_edge(int x, int y, int z) { t[++ii] = y; p[ii] = f[x]; f[x] = ii; wei[ii] = z; } void push (int to, int wei) { if (dist[to] <= wei) return ; if (S.find(make_pair(dist[to], to)) != S.end()) S.erase(S.find(make_pair(dist[to], to))); dist[to] = wei; par[to] = vn; S.insert(make_pair(dist[to], to)); } void deikstr (int source) { for(int i = 1; i <= n; i++) dist[i] = 1000000000; push(source, 0); while (S.size() > 0) { vn = S.begin()->second; S.erase(S.begin()); int q = f[vn]; while (q > 0) { push(t[q], dist[vn] + wei[q]); q = p[q]; } } } void getpath_to (int k) { wn = 0; while (k != s) { w[++wn] = k; k = par[k]; } reverse(w + 1, w + wn + 1); } int pn, path[MAXN], take_after, put_after, occurs[MAXN], it, last[MAXN]; vector vec2[MAXN]; long long ret = 0, alll = 0; void go_by_path () { ++it; for(int i = 1; i <= pn; i++) { occurs[path[i]] = it; last[path[i]] = i; } int remain = W - v[choice]; for(int i = 1; i <= pn; i++) { int node = path[i]; if (take_after == i) { ++an; ax[an] = 1; ay[an] = choice; } if (put_after == i) { ++an; ax[an] = 2; ay[an] = choice; remain += v[choice]; } for(int j = 0; j < vec2[node].size(); j++) { ++an; ax[an] = 2; ay[an] = vec2[node][j]; remain += v[vec2[node][j]]; ret += c[vec2[node][j]]; } vec2[node].clear(); for(int j = 0; j < vec[node].size(); j++) { int xx = vec[node][j].second; if (used[xx] || remain < v[xx] || occurs[b[xx]] != it || last[b[xx]] < i) continue ; used[xx] = true; remain -= v[xx]; assert(remain >= 0); vec2[b[xx]].push_back(xx); ++an; ax[an] = 1; ay[an] = xx; } if (i < pn) { ++an; ax[an] = 0; ay[an] = path[i + 1]; } } } int main () { // freopen("input.txt", "r", stdin); cin >> n >> m; assert(1 <= n && n <= 100000); assert(1 <= m && m <= 100000); for(int i = 1; i <= m; i++) { cin >> x >> y >> z; assert(1 <= x && x <= n); assert(1 <= y && y <= n); assert(x != y); assert(1 <= z && z <= 100); add_edge(x, y, z); add_edge(y, x, z); } cin >> k; assert(1 <= k && k <= 100000); for(int i = 1; i <= k; i++) { cin >> a[i] >> b[i] >> v[i] >> c[i]; assert(1 <= a[i] && a[i] <= n); assert(1 <= b[i] && b[i] <= n); assert(a[i] != b[i]); alll += c[i]; vec[a[i]].push_back(make_pair(v[i], i)); } for(int i = 1; i <= n; i++) sort(vec[i].begin(), vec[i].end()); cin >> s >> d >> W; assert(1 <= s && s <= n); assert(1 <= d && d <= 100000); assert(1 <= W && W <= 1000000000); for(int i = 1; i <= k; i++) { assert(1 <= v[i] && v[i] <= W); assert(1 <= c[i] && c[i] <= 1000000); } assert(1 <= d && d <= 100000); assert(1 <= s && s <= n); // deikstr(s); for(int i = 1; i <= n; i++) assert(dist[i] <= d); // while (d > 0) { choice = -1; for(int i = 1; i <= k; i++) if (!used[i] && 2 * dist[a[i]] + 2 * dist[b[i]] <= d) { if (choice == -1) choice = i; else if (c[choice] < c[i]) { choice = i; } // break; } if (choice == -1) break; d -= 2 * dist[a[choice]] + 2 * dist[b[choice]]; used[choice] = true; getpath_to(a[choice]); pn = 0; path[pn = 1] = s; for(int i = 1; i <= wn; i++) path[++pn] = w[i]; take_after = pn; put_after = -1; for(int i = wn - 1; i >= 1; i--) { path[++pn] = w[i]; if (w[i] == b[choice]) { put_after = pn; } } if (wn != 0) { path[++pn] = s; if (s == b[choice]) { put_after = pn; } } // if (put_after == -1) { getpath_to(b[choice]); for(int i = 1; i <= wn; i++) path[++pn] = w[i]; put_after = pn; for(int i = wn - 1; i >= 1; i--) path[++pn] = w[i]; if (wn != 0) path[++pn] = s; } else d += 2 * dist[b[choice]]; go_by_path(); ret += c[choice]; } cerr << "I should have got " << ret << endl; cout << an << endl; for(int i = 1; i <= an; i++) cout << ax[i] << " " << ay[i] << endl; return 0; }