51nod 3188 字符王国
建图,有环输出-1,无环按照拓扑序dp,设状态为 \(dp[i][j]\) 第 \(i\) 个点,\(j\) 的字符的出现的最大次数,最后遍历每个点找到最大答案。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=3e5+10;
struct ss{
int to,next;
}e[N];
int n,m;
int cnt;
int head[N],in[N];
char c[N];
queue<int> q;
int dp[N][30];
void add(int u,int v){
e[cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt++;
}
int main() {
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++){
head[i]=-1;
}
cin>>(c+1);
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
add(u,v);
in[v]++;
}
for(int i=1;i<=n;i++){
if(in[i]==0){
q.push(i);
}
}
while(!q.empty()){
int x=q.front();
q.pop();
dp[x][c[x]-'a']++;
for(int i=head[x];~i;i=e[i].next){
int y=e[i].to;
for(int j=0;j<26;j++){
dp[y][j]=max(dp[y][j],dp[x][j]);
}
if(--in[y]==0){
q.push(y);
}
}
}
for(int i=1;i<=n;i++){
if(in[i]){
cout<<-1;
return 0;
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=0;j<26;j++){
ans=max(ans,dp[i][j]);
}
}
cout<<ans;
return 0;
}