package main import ( "bufio" "fmt" "math/bits" "math/rand" "os" "strings" "time" ) func main() { yuki1340() // demo() } // https://yukicoder.me/problems/no/1340 // 给定一个n个点m条边的有向图,求t步后可能所在的顶点个数(每一步必须移动到一个相邻点). // n<=100 m<=1e4 t<=1e18 func yuki1340() { in := bufio.NewReader(os.Stdin) out := bufio.NewWriter(os.Stdout) defer out.Flush() var n, m, t int fmt.Fscan(in, &n, &m, &t) mat := NewBooleanMatrix(n, n) for i := 0; i < m; i++ { var a, b int fmt.Fscan(in, &a, &b) mat.Set(a, b, true) } mat.IPow(t) res := 0 for i := 0; i < n; i++ { if mat.Get(0, i) { res++ } } fmt.Fprintln(out, res) } // https://leetcode.cn/problems/course-schedule-iv/ func checkIfPrerequisite(numCourses int, prerequisites [][]int, queries [][]int) []bool { mat := NewBooleanMatrix(numCourses, numCourses) for _, p := range prerequisites { mat.Set(p[0], p[1], true) } trans := mat.TransitiveClosure() res := make([]bool, len(queries)) for i, q := range queries { res[i] = trans.Get(q[0], q[1]) } return res } func demo() { mat := NewBooleanMatrix(3, 3) mat.Set(0, 0, true) mat.Set(0, 1, true) mat.Set(1, 2, true) mat.Set(1, 0, true) // 5000*5000的矩阵乘法 => 836ms N_5000 := 5000 eye := Eye(N_5000) for i := 0; i < N_5000; i++ { for j := 0; j < N_5000; j++ { if rand.Intn(2) == 0 { eye.Set(i, j, true) } } } time1 := time.Now() Mul(eye, eye) time2 := time.Now() fmt.Println(time2.Sub(time1)) // 2000*2000的传递闭包 => 1.26s N_2000 := 2000 eye = Eye(N_2000) for i := 0; i < N_2000; i++ { for j := 0; j < N_2000; j++ { if rand.Intn(2) == 0 { eye.Set(i, j, true) } } } time3 := time.Now() eye.TransitiveClosure() time4 := time.Now() fmt.Println(time4.Sub(time3)) } type BooleanMatrix struct { ROW, COL int bs []Bitset } func NewBooleanMatrix(row, col int) *BooleanMatrix { bs := make([]Bitset, row) for i := range bs { bs[i] = NewBitset(col) } return &BooleanMatrix{ROW: row, COL: col, bs: bs} } func Eye(n int) *BooleanMatrix { res := NewBooleanMatrix(n, n) for i := 0; i < n; i++ { res.bs[i].Set(i) } return res } func Pow(mat *BooleanMatrix, k int) *BooleanMatrix { return mat.Copy().IPow(k) } func Mul(mat1, mat2 *BooleanMatrix) *BooleanMatrix { return mat1.Copy().IMul(mat2) } func Add(mat1, mat2 *BooleanMatrix) *BooleanMatrix { return mat1.Copy().IAdd(mat2) } // (A + I)^n 是传递闭包. func (bm *BooleanMatrix) TransitiveClosure() *BooleanMatrix { n := bm.ROW newMat := Add(bm, Eye(n)) newMat.IPow(n) return newMat } func (bm *BooleanMatrix) IPow(k int) *BooleanMatrix { res := Eye(bm.ROW) for k > 0 { if k&1 == 1 { res.IMul(bm) } bm.IMul(bm) k >>= 1 } res.bs, bm.bs = bm.bs, res.bs return bm } // square matrix func (bm *BooleanMatrix) IMul(mat *BooleanMatrix) *BooleanMatrix { n := mat.ROW res := NewBooleanMatrix(n, n) step := 1 dp := make([]Bitset, 1< n { r = n } for s := 1; s != (1 << step); s++ { lb := bits.TrailingZeros(uint(s)) dp[s] = Or(dp[s^(1<