【链接】 我是链接,点我呀:)
【题意】
在这里输入题意
【题解】
如果有环
->直接输出-1
(拓扑排序如果存在某个点没有入过队列,说明有环->即入队的节点个数不等于n
否则。
说明可以做拓扑排序。
->是一个有向无环图。
那么定义f[x][y]
表示x节点前面的某条路径中,字母y出现的最多次数是多少次。
在拓扑排序的时候做DP就好。
(可以百度:有向无环图 DP 应该有挺多类似的题的
从入度为0的点开始进行DP。
然后遇到分叉的时候也没关系
取两条路中对应字母的较大值就好。
所以最后f[x][y]中不同字母的最大值可能就是不同的路径了。
(是哪一条不好说
然后显然你尽可能地多走一点路总是没错的。
(走过的点越多,字母出现的频率越高。
所以肯定是从一个端点到达另外一个端点。
(即从入度为0的端点开始走.
【代码】
#include <bits/stdc++.h> using namespace std; const int N = 3e5; int n,m,k,flag[N+10],now,dp[N+10][30]; char s[N+10]; vector<int> g[N+10]; int ru[N+10],a[N+10]; queue<int> dl; int main(){ #ifdef LOCAL_DEFINE freopen("rush_in.txt", "r", stdin); #endif ios::sync_with_stdio(0),cin.tie(0); cin >> n >> m; cin >>(s+1); for (int i = 1;i <= m;i++){ int x,y; cin >> x >> y; g[x].push_back(y); ru[y]++; } for (int i = 1;i <= n;i++){ a[i] = s[i]-'a'+1; if (ru[i]==0){ dp[i][a[i]]++; dp[i][0] = 1; } } int num = 0; for (int i = 1;i <= n;i++) if (ru[i]==0){ num++; dl.push(i); ru[i] = -1; } while (!dl.empty()){ int x = dl.front(); dl.pop(); for (int y:g[x]){ if (ru[y]<=0) continue; if (dp[y][0]==0){ for (int i = 1;i <= 26;i++) dp[y][i] = dp[x][i]+(a[y]==i); }else{ for (int i = 1;i <=26;i++) dp[y][i] = max(dp[y][i],dp[x][i]+(a[y]==i)); } dp[y][0] = 1; ru[y]--; if (ru[y]==0){ num++; dl.push(y); } } } if (num!=n){ cout<<-1<<endl; return 0; } int ma = 0; for (int i = 1;i <= n;i++) if (dp[i][0]){ for (int j = 1;j <= 26;j++) ma = max(ma,dp[i][j]); } cout<<ma<<endl; return 0; }
来源:https://www.cnblogs.com/AWCXV/p/8396531.html