CF919D
Problem
给你一个有向图,每个点有一个小写字母权值,定义一条路径的权值是这条路径出现次数最多的字母的个数,求出这个图权值最大权值的路径的权值。
Solution
这个题很容易想到深搜,但是发现 $n\le 300000$,考虑动态规划,但是因为 $n\le 300000$,所以把我们的第二维空间卡的很死,而这道题又跟字符有关,那么很容易想到 $dp_{i,j}( 0\le j \le 25)$ 表示在第 $i$ 个位置字符为 $j$ 的答案。
考虑转移,很好想。如果当前的字符与 $j$ 相同,那么自然可以加一,否则不变,那么对于一条边:
$$
dp_{v,j}=max(dp_{v,j},dp_{u,j}+(s[v]==j))
$$
答案即为最大的一个,按照拓扑排序的顺序更新即可。
Code
短且易读的代码。
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
const LL N=3e5+5;
LL n,m,f[N][30],in[N],ans,cnt,x,y;
vector<LL> g[N];
string s;
queue<LL> q;
int main(){
cin>>n>>m;
cin>>s;
while(m--){
cin>>x>>y;
g[x].emplace_back(y);
in[y]++;
}
s=' '+s;
for(int i=1;i<=n;i++){
if(!in[i]){
q.push(i);
f[i][s[i]-'a']=1;
}
}
while(!q.empty()){
LL to=q.front();q.pop();
for(auto i : g[to]){
for(int j=0;j<26;j++) f[i][j] = max(f[i][j],f[to][j] + LL(bool(s[i]-'a'==j))),ans=max(ans,f[i][j]);
if(!(--in[i])){
q.push(i);
}
}
cnt++;
}
cout<<(cnt<n ? -1 : ans);
return 0;
}