結果

問題 No.1288 yuki collection
ユーザー 草苺奶昔草苺奶昔
提出日時 2023-03-11 20:35:54
言語 Go
(1.22.1)
結果
AC  
実行時間 757 ms / 5,000 ms
コード長 3,911 bytes
コンパイル時間 13,795 ms
コンパイル使用メモリ 218,440 KB
実行使用メモリ 17,364 KB
最終ジャッジ日時 2023-10-18 10:17:57
合計ジャッジ時間 24,211 ms
ジャッジサーバーID
(参考情報)
judge13 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,348 KB
testcase_01 AC 1 ms
4,348 KB
testcase_02 AC 2 ms
4,348 KB
testcase_03 AC 2 ms
4,348 KB
testcase_04 AC 2 ms
4,348 KB
testcase_05 AC 1 ms
4,348 KB
testcase_06 AC 1 ms
4,348 KB
testcase_07 AC 2 ms
4,348 KB
testcase_08 AC 3 ms
4,348 KB
testcase_09 AC 2 ms
4,348 KB
testcase_10 AC 3 ms
4,348 KB
testcase_11 AC 1 ms
4,348 KB
testcase_12 AC 2 ms
4,348 KB
testcase_13 AC 682 ms
8,876 KB
testcase_14 AC 662 ms
17,284 KB
testcase_15 AC 538 ms
8,880 KB
testcase_16 AC 528 ms
8,892 KB
testcase_17 AC 686 ms
17,248 KB
testcase_18 AC 744 ms
15,204 KB
testcase_19 AC 696 ms
15,120 KB
testcase_20 AC 710 ms
17,300 KB
testcase_21 AC 535 ms
8,804 KB
testcase_22 AC 527 ms
8,752 KB
testcase_23 AC 610 ms
17,136 KB
testcase_24 AC 717 ms
17,244 KB
testcase_25 AC 721 ms
17,364 KB
testcase_26 AC 757 ms
17,296 KB
testcase_27 AC 290 ms
8,896 KB
testcase_28 AC 351 ms
8,800 KB
testcase_29 AC 349 ms
8,892 KB
testcase_30 AC 14 ms
8,128 KB
testcase_31 AC 20 ms
8,248 KB
testcase_32 AC 21 ms
8,372 KB
testcase_33 AC 135 ms
8,380 KB
testcase_34 AC 176 ms
8,348 KB
testcase_35 AC 164 ms
8,344 KB
testcase_36 AC 170 ms
8,412 KB
testcase_37 AC 188 ms
8,472 KB
testcase_38 AC 140 ms
8,400 KB
testcase_39 AC 135 ms
8,384 KB
testcase_40 AC 5 ms
5,668 KB
testcase_41 AC 1 ms
4,348 KB
testcase_42 AC 1 ms
4,348 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

package main

import (
	"bufio"
	"fmt"
	"os"
)

const INF int = 1e18

// 拆点
func removeYuki(s string, scores []int) int {
	n := len(s)
	A := func(i int) int { return i }
	B := func(i int) int { return n + 1 + i }
	C := func(i int) int { return 2*(n+1) + i }
	D := func(i int) int { return 3*(n+1) + i }
	E := func(i int) int { return 4*(n+1) + i }
	mcmf := NewMinCostFlow(5*n+5, A(0), E(n))
	for i := 0; i < n; i++ {
		mcmf.AddEdge(A(i), A(i+1), n, 0)
		mcmf.AddEdge(B(i), B(i+1), n, 0)
		mcmf.AddEdge(C(i), C(i+1), n, 0)
		mcmf.AddEdge(D(i), D(i+1), n, 0)
		mcmf.AddEdge(E(i), E(i+1), n, 0)
	}
	for i := 0; i < n; i++ {
		if s[i] == 'y' {
			mcmf.AddEdge(A(i), B(i+1), 1, -scores[i])
		} else if s[i] == 'u' {
			mcmf.AddEdge(B(i), C(i+1), 1, -scores[i])
		} else if s[i] == 'k' {
			mcmf.AddEdge(C(i), D(i+1), 1, -scores[i])
		} else if s[i] == 'i' {
			mcmf.AddEdge(D(i), E(i+1), 1, -scores[i])
		}
	}

	slope := mcmf.Slope()
	res := 0
	for _, s := range slope {
		res = max(res, -s[1])
	}
	return res
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

type MinCostFlow struct {
	AddEdge func(from, to, cap, cost int)
	Work    func() (maxFlow int, minCost int)
	Slope   func() [][2]int // (flow, cost)
}

func NewMinCostFlow(n, start, end int) *MinCostFlow {
	type neighbor struct {
		to   int
		rid  int // rid 为反向边在邻接表中的下标
		cap  int // 边的残量
		cost int
		eid  int // -1表示是反向边
	}

	graph := make([][]neighbor, n)
	ei := 0
	addEdge := func(from, to, cap, cost, eid int) {
		graph[from] = append(graph[from], neighbor{to, len(graph[to]), cap, cost, eid})
		graph[to] = append(graph[to], neighbor{from, len(graph[from]) - 1, 0, -cost, -1})
	}

	dist := make([]int, len(graph))
	type vi struct{ v, i int }
	pre := make([]vi, len(graph))
	spfa := func() bool {
		for i := range dist {
			dist[i] = INF
		}
		dist[start] = 0
		inQueue := make([]bool, len(graph))
		inQueue[start] = true
		queue := []int{start}
		for len(queue) > 0 {
			cur := queue[0]
			queue = queue[1:]
			inQueue[cur] = false
			for i, edge := range graph[cur] {
				if edge.cap == 0 {
					continue
				}
				next := edge.to
				if cand := dist[cur] + int(edge.cost); cand < dist[next] {
					dist[next] = cand
					pre[next] = vi{cur, i}
					if !inQueue[next] {
						queue = append(queue, next)
						inQueue[next] = true
					}
				}
			}
		}
		return dist[end] < INF
	}

	// ek
	Work := func() (maxFlow int, minCost int) {
		for spfa() {
			// 沿 st-end 的最短路尽量增广
			flow := INF
			for cur := end; cur != start; {
				p := pre[cur]
				if c := graph[p.v][p.i].cap; c < flow {
					flow = c
				}
				cur = p.v
			}
			for cur := end; cur != start; {
				p := pre[cur]
				edge := &graph[p.v][p.i]
				edge.cap -= flow
				graph[cur][edge.rid].cap += flow
				cur = p.v
			}
			maxFlow += flow
			minCost += dist[end] * flow
		}
		return
	}

	Slope := func() (slope [][2]int) {
		maxFlow, minCost := 0, 0
		for spfa() {
			// 沿 st-end 的最短路尽量增广
			flow := INF
			for cur := end; cur != start; {
				p := pre[cur]
				if c := graph[p.v][p.i].cap; c < flow {
					flow = c
				}
				cur = p.v
			}
			for cur := end; cur != start; {
				p := pre[cur]
				edge := &graph[p.v][p.i]
				edge.cap -= flow
				graph[cur][edge.rid].cap += flow
				cur = p.v
			}
			maxFlow += flow
			minCost += dist[end] * flow
			slope = append(slope, [2]int{maxFlow, minCost})
		}
		return
	}

	AddEdge := func(from, to, cap, cost int) {
		addEdge(from, to, cap, cost, ei)
		ei++
	}

	return &MinCostFlow{
		AddEdge: AddEdge,
		Work:    Work,
		Slope:   Slope,
	}
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	var n int
	fmt.Fscan(in, &n)
	var s string
	fmt.Fscan(in, &s)
	scores := make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Fscan(in, &scores[i])
	}
	fmt.Fprintln(out, removeYuki(s, scores))
}
0