虽然赛中做出来了,也是一眼拓扑排序,但是转移方程部分一开始想歪了,所以简单记录一下。
(要是第一次没想歪,就上大分了)
思路
看到有向图,加上还需要判环,所以肯定想拓扑排序
1.拓扑排序判环的话,我们只需要把入度为0的点加入队列中,不断的跑图即可,如果每个点都被到达了,说明不存在环。
2.那么对于要计算的答案的话,因为小写字母只有26个,所以我们维护一下每个字符在该点能出现的最大次数即可。
对于从点x到点y,即更新点y时候每个字符出现的最多次数
dp[y][i]=max(dp[y][i],dp[x][i]+(colors[y]-‘a’==i))
dp[i][j]表示到达点i时,字符j出现的最多的次数
代码
int du[1<<20],dp[1<<20][26];
class Solution {
public:
vector<int> e[1<<20];
int largestPathValue(string colors, vector<vector<int>>& edges) {
int n=colors.size();
for(int i=0;i<n;i++){
du[i]=0;
for(int j=0;j<26;j++){
dp[i][j]=0;
}
}
for(auto &x:edges){
du[x[1]]++;
e[x[0]].push_back(x[1]);
}
queue<int> que;
for(int i=0;i<n;i++){
if(!du[i]){
dp[i][colors[i]-'a']=1;
que.push(i);
}
}
int ans=1,cnt=0;
while(!que.empty()){
int x=que.front();
++cnt;
que.pop();
for(auto &y:e[x]){
//从x向y转移,保留字符j出现次数最多的那个
for(int j=0;j<26;j++){
dp[y][j] =max(dp[y][j],dp[x][j]+(colors[y]-'a'==j));
ans=max(ans,dp[y][j]);
}
if(--du[y]==0){
que.push(y);
}
}
}
if(cnt!=n) return -1;
return ans;
}
};