codeforces 919D Substring (记忆化搜索)(dp)

链接:http://codeforces.com/problemset/problem/919/D

题意: 每个节点有个颜色,现在有n 个节点和m条边,现在要找出一条路径使得走过的点的颜色相同的数量最大。输出数量。可能出现环或者平行边。如果答案为inf 输出-1。

思路: 每个节点只受其后边节点(拓扑)的影响,意思是我如果能够确定该节点后边所有节点的状态,那么这个节点肯定也是能确定的,并且满足没有后效性。,所以我可以对每个节点只搜一遍,如果下次搜到这个节点就直接返回。这样就会很快了。当然要先确定有没有-1的情况,既拓扑一下,如果有一个点并没有被拓扑到,那么肯定是有-1的情况。

代码:

#include<bits/stdc++.h>

using namespace std;
const int N =3e5+5;
int n,m;
char s[N];
int flag[N];
int vis[N];
int num[N];
int inde[N];
int tmp[N];
vector< int >ve[N];
int res;
int Ans;
int dp[N][30];

void dfs(int u)
{
    if(vis[u]!=-1) return ;
    if(ve[u].size()==0){
        dp[u][num[u]]++;
        vis[u]=1;
        return ;
    }
    for(int i=0;i<ve[u].size();i++){
        int v=ve[u][i];
        dfs(v);
        for(int j=1;j<=26;j++){
            if(j==num[u]){
                dp[u][j]=max(dp[u][j],dp[v][j]+1);
            }
            else dp[u][j]=max(dp[u][j],dp[v][j]);
        }
    }
    vis[u]=1;
    return ;
}

int main()
{
    scanf("%d %d",&n,&m);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++){
        num[i]=s[i]-'a'+1;
    }
    int u,v;
    for(int i=1;i<=m;i++){
        scanf("%d %d",&u,&v);
        ve[u].push_back(v);
        inde[v]++;
        tmp[v]++;
    }
    queue<int >q;
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(inde[i]==0){
            q.push(i);
            vis[i]=1;
            cnt++;
        }
    }

    while(!q.empty()){
        u=q.front(); q.pop();
        for(int i=0;i<ve[u].size();i++){
            int v=ve[u][i];
            tmp[v]--;
            if(tmp[v]==0){
                vis[v]=1;
                q.push(v);
                cnt++;
            }
        }
    }
    if(cnt!=n){
        printf("-1\n");
        return 0;
    }
    memset(vis,-1,sizeof(vis));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=26;j++){
            dp[i][j]=0;
        }
    }

    for(int i=1;i<=n;i++){
        if(inde[i]==0){
            dfs(i);
            for(int j=1;j<=26;j++){
                Ans=max(Ans,dp[i][j]);
            }
        }
    }
    printf("%d\n",Ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yjt9299/article/details/82622778