CodeForces 919D Substring 拓扑排序+dp

版权声明:本博客内容基本为原创,如有问题欢迎联系,未经允许请勿转载 https://blog.csdn.net/qq_41955236/article/details/82110715

D. Substring

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a graph with nn nodes and mm directed edges. One lowercase letter is assigned to each node. We define a path's value as the number of the most frequently occurring letter. For example, if letters on a path are "abaca", then the value of that path is 33. Your task is find a path whose value is the largest.

Input

The first line contains two positive integers n,mn,m (1≤n,m≤3000001≤n,m≤300000), denoting that the graph has nn nodes and mm directed edges.

The second line contains a string ss with only lowercase English letters. The ii-th character is the letter assigned to the ii-th node.

Then mm lines follow. Each line contains two integers x,yx,y (1≤x,y≤n1≤x,y≤n), describing a directed edge from xx to yy. Note that xx can be equal to yy and there can be multiple edges between xx and yy. Also the graph can be not connected.

Output

Output a single line with a single integer denoting the largest value. If the value can be arbitrarily large, output -1 instead.

Examples

input

5 4
abaca
1 2
1 3
3 4
4 5

output

3

input

6 6
xzyabc
1 2
3 1
2 3
5 4
4 3
6 4

output

Copy

-1

input

10 14
xzyzyzyzqx
1 2
2 4
3 5
4 5
2 6
6 8
6 5
2 10
3 9
10 9
4 6
1 10
2 8
3 7

output

4

Note

In the first sample, the path with largest value is 1→3→4→5 1→3→4→5. The value is 33 because the letter 'a' appears 33 times.


题意:

       给你一个长度为n的字符串,第i个字符代表第i个结点的字符,现在给你m条单向边。一条路径的权值大小是这条路上出现次数最多的字母的出现次数,即假设有一条路径为经过的结点上的字母为a\rightarrow b\rightarrow a\rightarrow b\rightarrow a,则这条路径的权值为3,因为出现次数最多的为a,出现三次,现在要求你找出一条权值最大的路,如果存在一条权值最大的为定值的路,输出该权值,如果最大值可以为任意值,则输出-1

做法:

     很明显,如果出现了强连通分量,那么一定输出-1,所以一开始我还想用tarjan来做,可是后来就不知道怎么处理了,看了大神的题解才突然想起来拓扑排序,已经很久没有碰到要用这个知识点做的题目了,所以一下子还真的没想到,虽然有应该从入度为0的点开始跑这样的想法。这道题就是拓扑排序加上dp,dp[i][j]代表到达第i个结点时候经过了第j个字母的最大次数。其他的应该也不用解释了,知道是拓扑+dp之后应该挺好做了的。


#include<queue>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=300005;
int cnt,head[maxn],n,m,now;
int in[maxn],dp[maxn][26];
char s[maxn];
vector<int> ans;
struct node{
    int to,next;
}e[maxn*2];
void add(int u,int v){
    e[cnt].to=v;
    e[cnt].next=head[u],head[u]=cnt++;
}
void init(){
    memset(head,-1,sizeof(head));
    cnt=0;
}
int topo(){
    queue<int> q;
    int now=0;
    for(int i=1;i<=n;i++){
        if(!in[i]){
            q.push(i);
            dp[i][s[i]-'a']++;
        }
    }
    while(!q.empty()){
        int u=q.front(); q.pop();
        now++;
        for(int i=head[u];~i;i=e[i].next){
            int t=e[i].to,add=s[t]-'a';
            for(int j=0;j<26;j++){
                dp[t][j]=max(dp[t][j],dp[u][j]+(j==add?1:0));
            }
            if(--in[t]==0){
                q.push(t);
            }
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<26;j++)
            ans=max(ans,dp[i][j]);
    }
    if(now!=n) return -1;
    return ans;
}
int main(){
    init();
    int x,y;
    scanf("%d%d%s",&n,&m,s+1);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        add(x,y);
        in[y]++;
    }
    printf("%d\n",topo());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41955236/article/details/82110715