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
",maxx);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lemon-jade/p/8401209.html