You are given a graph with n nodes and m 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 3. Your task is find a path whose value is the largest.
The first line contains two positive integers n, m (1 ≤ n, m ≤ 300 000), denoting that the graph has n nodes and m directed edges.
The second line contains a string s with only lowercase English letters. The i-th character is the letter assigned to the i-th node.
Then m lines follow. Each line contains two integers x, y (1 ≤ x, y ≤ n), describing a directed edge from x to y. Note that x can be equal to y and there can be multiple edges between x and y. Also the graph can be not connected.
Output a single line with a single integer denoting the largest value. If the value can be arbitrarily large, output -1 instead.
5 4 abaca 1 2 1 3 3 4 4 5
3
6 6 xzyabc 1 2 3 1 2 3 5 4 4 3 6 4
-1
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
4
In the first sample, the path with largest value is 1 → 3 → 4 → 5. The value is 3 because the letter 'a' appears 3 times.
题意:给一串小写英文字母的字符,并根据下标建单向边,建完图之后,寻找一条路径使得其中重复字母最多,若重复无限次,则输出-1。
思路:拓扑排序!!居然一开始没有想到!!拓扑排序每次更新到达节点对应26个字母的之前连接路径中的最大重复数。如果有回路则输出-1。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
#define maxn 300010
using namespace std;
bool vis[maxn];
int ind[maxn];
int l[maxn][26];
vector<int>map[maxn];
char s[maxn+10];
int viss;
int ans;
queue<int>q;
void topo(int u)
{
ind[u]--;
vis[u]=1;
viss++;
l[u][s[u]-'a']++;
for(int j=0;j<26;j++)
{
ans=max(ans,l[u][j]);
}
for(int i=0;i<map[u].size();i++)
{
if(!vis[map[u][i]])
{
for(int j=0;j<26;j++)
{
l[map[u][i]][j]=max(l[map[u][i]][j],l[u][j]);
}
ind[map[u][i]]--;
if(ind[map[u][i]]==0)q.push(map[u][i]);
}
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<maxn;i++)map[i].clear();
while(!q.empty())q.pop();
memset(vis,0,sizeof(vis));
memset(l,0,sizeof(l));
memset(ind,0,sizeof(ind));
scanf("%s",s+1);
int x,y;
for(int i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
map[x].push_back(y);
ind[y]++;
}
int maxt=0;
viss=0;
ans=0;
bool flag=true;
for(int i=1;i<=n;i++)
{
if(ind[i]==0)q.push(i);
}
while(!q.empty())
{
topo(q.front());
q.pop();
}
if(viss<n)
{
printf("-1\n");
continue;
}
printf("%d\n",ans);
}
}
太久没写拓扑排序,比赛的时候居然忘记了用队列,t掉了。。。两分钟的事情。。。
代码写的很乱。