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
Note
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.
http://codeforces.com/problemset/problem/919/D
题意:
解题思路:
#include<stdio.h> #include<vector> #include<queue> #include<iostream> using namespace std; int n,m,res; const int Maxn = 300005; char str[Maxn]; int indegree[Maxn]; int _next[Maxn]; int dp[Maxn]; queue<int>q; vector<int>head; vector <int> neigh[Maxn]; bool circle()//拓扑排序中的判环法 { int rco=0; for(int i=1;i<=n;i++) { if(indegree[i]==0)//找出入度为0的点 { q.push(i);//判环用的队列 head.push_back(i);//搜索用的数组 rco++;//记录出现的次数 } } while(!q.empty()) { int temp=q.front(); q.pop(); for(int i=0;i<neigh[temp].size();i++) { int v=neigh[temp][i]; indegree[v]--; if(indegree[v]==0)//当产生新的入度为零的点的时候入队,并放进搜索用的数组 { q.push(v); head.push_back(v); rco++;//这里也是记录 } } } if(rco<n)//如果最终入度为零的点少于全部的点那证明成环了,建议画图试试看 { return true; } return false; } void init(int v) { } int main() { ios::sync_with_stdio(false); while(cin>>n>>m) { res=0; for(int i=1;i<=n;i++) { cin>>str[i]; } for(int i=1;i<=m;i++) { int a,b; cin>>a>>b; neigh[a].push_back(b);//把b放进a对应的集合中 indegree[b]++; } if(circle()) { cout<<"-1"<<endl; continue; } for (char let = 'a'; let <= 'z'; let++)//一个一个字母对 { for (int i = head.size()-1; i >=0; i--)//从后面开始搜索保证从最低层级开始递推 { int v =head[i]; // cout<<"-----------"<<v<<endl; int my = str[v] == let; dp[v] = my; for (int j = 0; j < neigh[v].size(); j++) { dp[v] = max(dp[v], dp[neigh[v][j]] + my); } res = max(res, dp[v]); } } printf("%d\n", res); } }第二种是深搜递归型的,这种是一条一条路从最深递归上来的。
#include <cstdio> #include <iostream> #include <vector> #include <set> #include <map> #include <cmath> #include <string> #include <cstring> #include <sstream> #include <queue> #include <iomanip> #include <algorithm> #pragma comment(linker, "/STACK:16000000") using namespace std; const int Maxn = 300005; int n, m; char str[Maxn]; vector <int> neigh[Maxn]; int tk[Maxn]; vector <int> seq; int dp[Maxn]; int res; bool findLoop(int v) { if (tk[v] == 2) return false; if (tk[v] == 1) return true; tk[v] = 1; for (int i = 0; i < neigh[v].size(); i++) if (findLoop(neigh[v][i])) return true; tk[v] = 2; seq.push_back(v); return false; } int main() { scanf("%d %d", &n, &m); scanf("%s", str + 1); for (int i = 0; i < m; i++) { int a, b; scanf("%d %d", &a, &b); neigh[a].push_back(b); } for (int i = 1; i <= n; i++) if (!tk[i]) { if (findLoop(i)) { printf("-1\n"); return 0; } } for (char let = 'a'; let <= 'z'; let++) { for (int i = 0; i < seq.size(); i++) { int v = seq[i]; int my = str[v] == let; dp[v] = my; for (int j = 0; j < neigh[v].size(); j++) { dp[v] = max(dp[v], dp[neigh[v][j]] + my); } res = max(res, dp[v]); } } printf("%d\n", res); return 0; }