边转点,然后前缀优化。
清空的时候要清空倍增数组!
/*
QiuQiu /qq
____ _ _ __
/ __ \ (_) | | / /
| | | | _ _ _ | | _ _ / / __ _ __ _
| | | | | | | | | | | | | | | | / / / _` | / _` |
| |__| | | | | |_| | | | | |_| | / / | (_| | | (_| |
\___\_\ |_| \__,_| |_| \__, | /_/ \__, | \__, |
__/ | | | | |
|___/ |_| |_|
*/
#include <bits/stdc++.h>
using namespace std;
class Input {
#define MX 1000000
private :
char buf[MX], *p1 = buf, *p2 = buf;
inline char gc() {
if(p1 == p2) p2 = (p1 = buf) + fread(buf, 1, MX, stdin);
return p1 == p2 ? EOF : *(p1 ++);
}
public :
Input() {
#ifdef Open_File
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
#endif
}
template <typename T>
inline Input& operator >>(T &x) {
x = 0; int f = 1; char a = gc();
for(; ! isdigit(a); a = gc()) if(a == '-') f = -1;
for(; isdigit(a); a = gc())
x = x * 10 + a - '0';
x *= f;
return *this;
}
inline Input& operator >>(char &ch) {
while(1) {
ch = gc();
if(ch != '\n' && ch != ' ') return *this;
}
}
inline Input& operator >>(char *s) {
int p = 0;
while(1) {
s[p] = gc();
if(s[p] == '\n' || s[p] == ' ' || s[p] == EOF) break;
p ++;
}
s[p] = '\0';
return *this;
}
#undef MX
} Fin;
class Output {
#define MX 1000000
private :
char ouf[MX], *p1 = ouf, *p2 = ouf;
char Of[105], *o1 = Of, *o2 = Of;
void flush() { fwrite(ouf, 1, p2 - p1, stdout); p2 = p1; }
inline void pc(char ch) {
* (p2 ++) = ch;
if(p2 == p1 + MX) flush();
}
public :
template <typename T>
inline Output& operator << (T n) {
if(n < 0) pc('-'), n = -n;
if(n == 0) pc('0');
while(n) *(o1 ++) = (n % 10) ^ 48, n /= 10;
while(o1 != o2) pc(* (--o1));
return *this;
}
inline Output & operator << (char ch) {
pc(ch); return *this;
}
inline Output & operator <<(const char *ch) {
const char *p = ch;
while( *p != '\0' ) pc(* p ++);
return * this;
}
~Output() { flush(); }
#undef MX
} Fout;
#define cin Fin
#define cout Fout
#define endl '\n'
using LL = long long;
const int N = 2e6 + 10;
int loc[N], whi[N];
namespace Trie {
int n;
vector<int> e[N];
void push(int x, int y) { e[x].push_back(y); e[y].push_back(x); }
int lg[N];
int fa[N][20], dep[N], dfn[N];
void dfs(int x, int fx) {
// cerr << x << endl;
fa[x][0] = fx; dep[x] = dep[fx] + 1; dfn[x] = ++ dfn[0];
for(int i = 1; i <= lg[dep[x]]; i ++) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for(int y : e[x]) if(y != fx) dfs(y, x);
}
int lca(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
while(dep[x] > dep[y]) x = fa[x][lg[dep[x] - dep[y]]];
if(x == y) return x;
for(int i = lg[dep[x]]; i >= 0; i --) if(fa[x][i] ^ fa[y][i]) x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int dep_lca(int x, int y) { return dep[lca(x, y)] - 1; }
void build() {
dfn[0] = 0;
memset(fa, 0, sizeof(fa));
for(int i = 2; i <= n; i ++) lg[i] = lg[i >> 1] + 1;
dfs(1, 0);
}
inline bool cmp(int x, int y) { return dfn[whi[x]] < dfn[whi[y]]; }
}
using Trie :: dep_lca;
using Trie :: cmp;
int n, m;
// 点 边 trie
vector<int> node[N];
int trie[N];
struct edge {
int to, next, w;
} e[N << 2];
int cnt, head[N];
void push(int x, int y, int w) {
//cerr << x << ' ' << y << ' ' << w << endl;
e[++ cnt] = (edge) {y, head[x], w}; head[x] = cnt;
}
int tot, S;
void clr() {
cnt = 0;
for(int i = 1; i <= tot; i ++) head[i] = 0;
for(int i = 1; i <= n; i ++) node[i].clear();
for(int i = 1; i <= Trie :: n; i ++) Trie :: e[i].clear();
memset(loc, 0, sizeof(loc));
tot = 0; S = 0;
}
void linkit(int id) {
static int pre_out[N], pre_in[N], suf_out[N], suf_in[N], lk[N];
vector<int> &v = node[id]; //cerr << v.size() << endl;
//cerr << v[0] << endl;
sort(v.begin(), v.end(), cmp);
int sz = v.size();
for(int i = 1; i <= sz; i ++) pre_in[i] = ++ tot;
for(int i = 1; i <= sz; i ++) pre_out[i] = ++ tot;
for(int i = 1; i <= sz; i ++) suf_in[i] = ++ tot;
for(int i = 1; i <= sz; i ++) suf_out[i] = ++ tot;
for(int i = 2; i <= sz; i ++) push(pre_out[i - 1], pre_out[i], 0), push(pre_in[i], pre_in[i - 1], 0);
for(int i = sz - 1; i >= 1; i --) push(suf_in[i], suf_in[i + 1], 0), push(suf_out[i + 1], suf_out[i], 0);
for(int i = 0; i < sz - 1; i ++) lk[i + 1] = dep_lca(whi[v[i]], whi[v[i + 1]]);
//for(int i = 1; i <= sz; i ++) {
// cerr << v[i - 1] << ' ';
//} cerr << endl;
for(int i = 1; i <= sz; i ++) {
int x = v[i - 1]; //cerr << x << endl;
//cerr << x << ' ' << pre_out[i] << endl;
if(x > m) push(x, pre_out[i], 0), push(x, suf_out[i], 0);
else push(pre_in[i], x, 0), push(suf_in[i], x, 0);
}
for(int i = 1; i <= sz - 1; i ++) {
push(pre_out[i], suf_in[i + 1], lk[i]);
push(suf_out[i + 1], pre_in[i], lk[i]);
}
}
using ll = long long;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll dis[N];
int vis[N];
void dijskra() {
memset(dis, 0x3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
dis[S] = 0;
priority_queue<pair<int, int> > q;
q.push({0, S});
while(q.size()) {
int x = q.top().second; q.pop();
if(vis[x]) continue;
vis[x] = 1;
// cerr << x << endl;
for(int i = head[x]; i; i = e[i].next) {
int y = e[i].to, w = e[i].w;
// cerr << x << ' ' << y << ' ' << w << endl;
if(dis[y] > dis[x] + w) {
dis[y] = dis[x] + w;
q.push({- dis[y], y});
}
}
}
//cerr << dis[1] << endl;
}
ll ans[N];
void solve() {
cin >> n >> m >> Trie :: n;
tot = m * 2; S = ++ tot;
for(int i = 1; i <= m; i ++) {
int a, b, c, d;
cin >> a >> b >> c >> d;
node[b].push_back(i + m);
node[a].push_back(i);
trie[i] = trie[i + m] = d;
loc[i + m] = b;
whi[i] = whi[i + m] = d;
push(i, i + m, c);
if(a == 1) {
push(S, i, 0);
// cerr << S << ' ' << i << endl;
}
}
for(int i = 1; i <= Trie :: n - 1; i ++) {
int x, y, w;
cin >> x >> y >> w;
Trie :: push(x, y);
// Trie :: push(y, x);
}
Trie :: build();//cerr << "ok" << endl;
// cout << dep_lca(4, 5) << endl;
for(int i = 1; i <= n; i ++) linkit(i);
// linkit(2);
// linkit(4);
dijskra();
for(int i = 1; i <= n; i ++) ans[i] = INF;
// for(int i = 1; i <= m * 2; i ++) cerr << loc[i] << endl;
// cerr << dis[6] << endl;
for(int i = 1; i <= m * 2; i ++) ans[loc[i]] = min(ans[loc[i]], dis[i]);
for(int i = 2; i <= n; i ++) cout << ans[i] << endl;
clr();
}
int main() {
//freopen("a.in", "r", stdin);
int Case; cin >> Case;
while(Case --) solve();
return 0;
}