D. Substring
D. Substring(919D)
题意:求从某一结点到另一结点,字母出现的次数最大值
dfs+记忆化搜索
若形成环,输出-1
digmax[i][j] 表示顶点是i, 单树下字母'a'+j 的个数
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; const int N=300007; char s[N]; int in[N],vis[N],vised[N],m,n,flag; int digmax[N][28]; //digmax[i][j] 表示顶点是i, 单树下字母'a'+j 的个数 vector<int>edge[N]; void dfs(int u) { if(vised[u]||flag) //判环 { flag=1; return; } vised[u]=1; if(vis[u]) //之前求过,直接返回 return; vis[u]=1; digmax[u][s[u]-'a']++; for(int i=0;i<edge[u].size();i++) { int v=edge[u][i]; dfs(v); vised[v]=0; for(int j=0;j<26;j++) digmax[u][j]=max(digmax[u][j],digmax[v][j]+(j==s[u]-'a')); } } int main() { int u,v,maxx=0; scanf("%d%d",&n,&m); scanf("%s",s+1); memset(in,0,sizeof(in)); memset(vis,0,sizeof(vis)); memset(vised,0,sizeof(vised)); memset(digmax,0,sizeof(digmax)); while(m--) { scanf("%d%d",&u,&v); edge[u].push_back(v); in[v]++; } flag=0; for(int i=1;i<=n;i++) if(!in[i]) dfs(i); for(int i=1;i<=n;i++) //判环 if(!vis[i]) flag=1; if(flag) puts("-1"); else { for(int i=1;i<=n;i++) for(int j=0;j<26;j++) maxx=max(maxx,digmax[i][j]); printf("%d\n",maxx); } return 0; }