LINK
Base
有n=1e5个点 的 有向图, 每个点有26种颜色
问对于任意一种路径中,同种颜色出现次数的最大值。(答案保证有解)
[0, A] -> [1, A] -> [2, A] -> [3, B] -> [4, B]
|
√
[5, A]
' 答案为4, 对应[0 -> 1 -> 2 -> 3 -> 5]这条路径。 A出现了4次 '
本题最最核心是,看似非常不起眼的: “答案保证有解” 这句话
我们假想,对于这个“有向图”来说,如果“有环”: 显然一旦进行死循环,则就是INF(无解)
因此,我们得到的这个图,其实是一个: DAG !!! 这非常重要
dp[1e5][26]: 以cur为起点,往下走, xxx
关键是,我们如何定义这个“xxx”
一般的拓扑dp是: xxx为, 从cur为起点往下走,的 “某条路径” 的值
'但,假如你这样定义, 你的dp[3] 就会得到 [3 -> 4]这个路径(因为他的ans=2) '
' 但是, 最终答案 dp[3]应该走的是[3 -> 5]这条路径。 '
那么,你可能会认为, xxx定义的 不是“某个路径”,而是“所有的路径”???
如果记录的是“所有路径”, 那太多了.......
那和暴力dfs还有什么区别。 首先,我们定义这个dp[cur] 就是 做“记忆化”的!!!
' 所有, 拓扑dp 都可以用 记忆化dfs,来替换!! '
所以,这个dp[cur] 就是做记忆化的, 即“他就是: 记录的 某一条路径 的值”!!!
但是不同的是, 你不是对cur记录的某一条路径,而是对cur的26种选择,记录路径!!!
“换句话说, 不是对cur进行的记忆化, 而是对cur的26个维度 进行记忆化”
比如你的3这个点, 你会记录: dp[3][B] = 2, dp[3][A] = 1;
这两个值, 是代表了 不同的路径!!
' 因为,最终答案 看的就是 某一个颜色的状态'
int ANS = 0;
FORR(i, n-1, 0, 1){
int cur = que[i];
int cur_num = A[cur] - 'a';
for(int j, i = head[cur];~i;i=nex[i]){
j = val[i];
FOR(z, 0, 25, 1){ ' 重点!! dp[cur][i = 0,1,2...] i不同,记录的是 完全不同的路径,但都是从cur为起点的路径 '
MAX(dp[cur][z], dp[j][z]);
}
}
dp[cur][cur_num] ++;
MAX(ANS, dp[cur][cur_num]);
}