Codeforces 919D:Substring(拓扑排序+DP)

本文探讨了一种算法,用于解决有向图中寻找具有最大字母出现次数的路径问题。给定一个带有字母标记的有向图,目标是找到一条路径,其上某字母出现的次数最多。文章详细介绍了使用拓扑排序来检测图中是否存在环,以及如何通过动态规划更新字母出现的最大次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D. Substring

time limit: per test3 seconds
memory limit: per test256 megabytes
inputstandard: input
outputstandard: output

You are given a graph with nnn nodes and mmm 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 333. Your task is find a path whose value is the largest.

Input

The first line contains two positive integers n,m(1≤n,m≤300000)n,m (1≤n,m≤300000)n,m(1n,m300000), denoting that the graph has nnn nodes and mmm directed edges.

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

Then m lines follow. Each line contains two integers x,y(1≤x,y≤n)x,y (1≤x,y≤n)x,y(1x,yn), describing a directed edge from xxx to yyy. Note that xxx can be equal to yyy and there can be multiple edges between xxx and yyy. 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-11 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

-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→51→3→4→51345. The value is 333 because the letter ‘a’ appears 333 times.

题意

给出有nnn个点和mmm条边的有向图,每个节点上有一个小写字母,求所有通路中出现次数最多的字母出现的次数,如果出现了无数次,输出−1-11

Solve

用拓扑排序判断图中是否有环,如果有环,那么环上的字母出现的次数为无限多次,输出−1-11
如果能够进行拓扑排序,对于每次遍历的节点,更新当前路上字母出现次数的最大值
dp[i][j]dp[i][j]dp[i][j]表示到达节点iii,字母′a′+j'a'+ja+j出现的最大次数

Code

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
#define INF 0x7f7f7f7f
const int maxn=1e6+10;
const int mod=1e9+7;
using namespace std;
int n,m;
char ch[maxn];
int visi[maxn];
// dp[i][j]表示到i位置,字母j出现的最多次数
int dp[maxn][50];
int cnt;
vector<int>v[maxn];
queue<int>que;
void topo()
{
	for(int i=1;i<=n;i++)
		if(!visi[i])
		{
			que.push(i);
			dp[i][ch[i]-'a']++;
		}
	while(!que.empty())
	{
		cnt++;
		int res=que.front();
		que.pop();
		int sz=v[res].size();
		for(int i=0;i<sz;i++)
		{
			visi[v[res][i]]--;
			if(!visi[v[res][i]])
				que.push(v[res][i]);
			for(int j=0;j<26;j++)
				dp[v[res][i]][j]=max(dp[v[res][i]][j],dp[res][j]+(ch[v[res][i]]-'a'==j));
		}
	}
	if(cnt<n)
		cout<<-1<<endl;
	else
	{
		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<<endl;
	}
}
int main(int argc, char const *argv[])
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>m;
	cin>>(ch+1);
	ms(visi,0);
	int x,y;
	for(int i=0;i<m;i++)
	{
		cin>>x>>y;
		v[x].push_back(y);
		visi[y]++;
	}
	topo();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值