package main
import (
"bufio"
"container/heap"
"fmt"
"os"
)
type Edge struct {
to int
w int64
}
var adj [][]Edge
var dist []int64
const INF int64 = 1e18
type PQItem struct {
dist int64
node int
}
type PQ []PQItem
func (p PQ) Len() int { return len(p) }
func (p PQ) Less(i, j int) bool { return p[i].dist < p[j].dist }
func (p PQ) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p *PQ) Push(x interface{}) {
*p = append(*p, x.(PQItem))
}
func (p *PQ) Pop() interface{} {
old := *p
n := len(old)
x := old[n-1]
*p = old[0 : n-1]
return x
}
func buildIn(node, start, end, offset int) {
if start == end {
adj[offset+node] = append(adj[offset+node], Edge{start, 0})
return
}
mid := (start + end) / 2
buildIn(2*node, start, mid, offset)
buildIn(2*node+1, mid+1, end, offset)
adj[offset+node] = append(adj[offset+node], Edge{offset + 2*node, 0})
adj[offset+node] = append(adj[offset+node], Edge{offset + 2*node+1, 0})
}
func buildOut(node, start, end, offset int) {
if start == end {
adj[start] = append(adj[start], Edge{offset+node, 0})
return
}
mid := (start + end) / 2
buildOut(2*node, start, mid, offset)
buildOut(2*node+1, mid+1, end, offset)
adj[offset + 2*node] = append(adj[offset + 2*node], Edge{offset+node, 0})
adj[offset + 2*node+1] = append(adj[offset + 2*node+1], Edge{offset+node, 0})
}
func getCanonical(node, start, end, ql, qr, offset int, cans *[]int) {
if ql > end || qr < start {
return
}
if ql <= start && end <= qr {
*cans = append(*cans, offset + node)
return
}
mid := (start + end) / 2
getCanonical(2*node, start, mid, ql, qr, offset, cans)
getCanonical(2*node+1, mid+1, end, ql, qr, offset, cans)
}
func main() {
in := bufio.NewReader(os.Stdin)
var n, q, s int
fmt.Fscan(in, &n, &q, &s)
segsize := 4 * (n + 1)
inStart := n + 1
outStart := inStart + segsize
total := outStart + segsize - 1
adj = make([][]Edge, total+1)
dist = make([]int64, total+1)
for i := range dist {
dist[i] = INF
}
buildIn(1, 1, n, inStart)
buildOut(1, 1, n, outStart)
for qi := 0; qi < q; qi++ {
var t int
fmt.Fscan(in, &t)
if t == 1 {
var v, u int
var w int64
fmt.Fscan(in, &v, &u, &w)
adj[v] = append(adj[v], Edge{u, w})
} else if t == 2 {
var v, l, r int
var w int64
fmt.Fscan(in, &v, &l, &r, &w)
var cans []int
getCanonical(1, 1, n, l, r, inStart, &cans)
for _, can := range cans {
adj[v] = append(adj[v], Edge{can, w})
}
} else if t == 3 {
var v, l, r int
var w int64
fmt.Fscan(in, &v, &l, &r, &w)
var cans []int
getCanonical(1, 1, n, l, r, outStart, &cans)
for _, can := range cans {
adj[can] = append(adj[can], Edge{v, w})
}
}
}
pq := &PQ{}
heap.Init(pq)
dist[s] = 0
heap.Push(pq, PQItem{0, s})
for pq.Len() > 0 {
item := heap.Pop(pq).(PQItem)
u := item.node
cost := item.dist
if cost > dist[u] {
continue
}
for _, e := range adj[u] {
to := e.to
newd := dist[u] + e.w
if newd < dist[to] {
dist[to] = newd
heap.Push(pq, PQItem{newd, to})
}
}
}
out := bufio.NewWriter(os.Stdout)
for i := 1; i <= n; i++ {
if i > 1 {
fmt.Fprint(out, " ")
}
if dist[i] == INF {
fmt.Fprint(out, -1)
} else {
fmt.Fprint(out, dist[i])
}
}
fmt.Fprintln(out)
out.Flush()
}