const int MAXN=1e5+5;
const LL inf=123456789123456789;
LL slope[MAXN<<1],b[MAXN<<1];
LL a[MAXN];
LL caly(int v,int x){
return slope[v]*a[x]+b[v];
}
namespace Tree{
int lef[MAXN<<2],rig[MAXN<<2],tag[MAXN<<2];
LL s[MAXN<<2];
void push_up(int k){
s[k]=min(s[k],min(s[k<<1],s[k<<1|1]));
}
void build(int k,int L,int R){
lef[k]=L,rig[k]=R,s[k]=inf;
if(L==R)return;
int M=L+R>>1;
build(k<<1,L,M);
build(k<<1|1,M+1,R);
}
void update(int k,int v){
s[k]=min(s[k],min(caly(v,lef[k]),caly(v,rig[k])));
if(!tag[k]){
tag[k]=v;
return;
}
int mid=lef[k]+rig[k]>>1;
LL y1=caly(v,mid),y2=caly(tag[k],mid);
if(lef[k]==rig[k]){
tag[k]=(y1<y2)?v:tag[k];
return;
}
if(y1<y2){
if(slope[v]<slope[tag[k]])
update(k<<1,tag[k]);
else if(slope[v]>slope[tag[k]])
update(k<<1|1,tag[k]);
tag[k]=v;
}
else{
if(slope[v]>slope[tag[k]])
update(k<<1,v);
else if(slope[v]<slope[tag[k]])
update(k<<1|1,v);
}
push_up(k);
}
void update(int k,int L,int R,int v){
if(L<=lef[k]&&rig[k]<=R)
update(k,v);
else{
int mid=lef[k]+rig[k]>>1;
if(mid>=L)
update(k<<1,L,R,v);
if(mid<R)
update(k<<1|1,L,R,v);
push_up(k);
}
}
LL query(int k,int L,int R){
if(L<=lef[k]&&rig[k]<=R)
return s[k];
LL ans=tag[k]==0?inf:min(caly(tag[k],max(lef[k],L)),caly(tag[k],min(rig[k],R)));
int mid=lef[k]+rig[k]>>1;
if(mid>=L)
ans=min(ans,query(k<<1,L,R));
if(mid<R)
ans=min(ans,query(k<<1|1,L,R));
return ans;
}
}
struct Edge{
int to,w,next;
}edge[MAXN<<1];
int head[MAXN],edge_cnt;
void Insert(int u,int v,int w){
edge[++edge_cnt]=Edge{v,w,head[u]};
head[u]=edge_cnt;
}
int d[MAXN],sz[MAXN],f[MAXN],dfn[MAXN],dfs_t;
int hson[MAXN],mson[MAXN],p[MAXN];
LL dis[MAXN];
void dfs1(int u,int fa){
sz[u]=1,f[u]=fa,mson[u]=0;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa)continue;
d[v]=d[u]+1;
dis[v]=dis[u]+edge[i].w;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>mson[u]){
hson[u]=v;
mson[u]=sz[v];
}
}
}
void dfs2(int u,int top){
dfn[u]=++dfs_t,p[u]=top;
a[dfs_t]=dis[u];
if(mson[u])
dfs2(hson[u],top);
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==f[u]||v==hson[u])
continue;
dfs2(v,v);
}
}
int lca(int u,int v){
while(p[u]!=p[v]){
if(d[p[u]]<d[p[v]])
swap(u,v);
u=f[p[u]];
}
return d[u]<d[v]?u:v;
}
void update(int u,int pu,int v){
while(p[u]!=p[pu]){
Tree::update(1,dfn[p[u]],dfn[u],v);
u=f[p[u]];
}
Tree::update(1,dfn[pu],dfn[u],v);
}
LL query(int u,int v){
LL ans=inf;
while(p[u]!=p[v]){
if(d[p[u]]<d[p[v]])
swap(u,v);
ans=min(ans,Tree::query(1,dfn[p[u]],dfn[u]));
u=f[p[u]];
}
if(d[u]>d[v])
swap(u,v);
return min(ans,Tree::query(1,dfn[u],dfn[v]));
}
int main()
{
int n=read_int(),m=read_int(),cnt=0;
_for(i,1,n){
int u=read_int(),v=read_int(),w=read_int();
Insert(u,v,w);
Insert(v,u,w);
}
Tree::build(1,1,n);
dfs1(1,0);
dfs2(1,1);
while(m--){
int opt=read_int(),u=read_int(),v=read_int();
if(opt==1){
LL a0=read_int(),b0=read_int();
int p=lca(u,v);
++cnt;
slope[cnt]=-a0,b[cnt]=a0*dis[u]+b0;
update(u,p,cnt);
++cnt;
slope[cnt]=a0,b[cnt]=a0*(dis[u]-2*dis[p])+b0;
update(v,p,cnt);
}
else
enter(query(u,v));
}
return 0;
}