拓扑dp反推、如何O(n)记录所有dfs路径

LINK

catalog

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]);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值