给你一个 有向图 ,它含有
n
个节点和m
条边。节点编号从0
到n - 1
。给你一个字符串
colors
,其中colors[i]
是小写英文字母,表示图中第i
个节点的 颜色 (下标从 0 开始)。同时给你一个二维数组edges
,其中edges[j] = [aj, bj]
表示从节点aj
到节点bj
有一条 有向边 。图中一条有效 路径 是一个点序列
x1 -> x2 -> x3 -> ... -> xk
,对于所有1 <= i < k
,从xi
到xi+1
在图中有一条有向边。路径的 颜色值 是路径中 出现次数最多 颜色的节点数目。请你返回给定图中有效路径里面的 最大颜色值 。如果图中含有环,请返回
-1
。
示例 1:
输入:colors = "abaca", edges = [[0,1],[0,2],[2,3],[3,4]] 输出:3 解释:路径 0 -> 2 -> 3 -> 4 含有 3 个颜色为 "a" 的节点(上图中的红色节点)。
示例 2:
输入:colors = "a", edges = [[0,0]] 输出:-1 解释:从 0 到 0 有一个环。
提示:
n == colors.length
m == edges.length
1 <= n <= 105
0 <= m <= 105
colors
只含有小写英文字母。0 <= aj, bj < n
比赛的时候一直在死扣深搜,一直超时,最后看了大神的代码,要不说人家是大神呢
我的想法是顺序找,但没想到如何剪枝,大佬的想法是逆序找,就是我先遍历到最后一个节点,如果这个节点的颜色和要找的一致,那么就是1
如果最后一个节点dp[y] = 1,然后递归回溯到上一个节点x,首先这个dp[x]最少就是1,因为下一个已经是1了,然后判断x的颜色和找的是否一致,一致的话dp[x] = 2
依次类推。。。。。
这种好处就是如果再次遍历到一个节点n,这个节点必定是已经被后面的值更新过了,所以只需要判断当前节点和n的大小,更新当前节点的值
说白了就是当前节点的值总是由上一个节点得到,这样就可以剪枝,减掉重复遍历的点。最后进入递归的点就是最大值
然后超时的点就是!!!!!参数,不要传参数,太坑了
class Solution {
public:
vector<int> vec[100005];
int vis[100005] = {0};
int out = 1;
string str ;
int maxn[100005];
void dfs(int col,int x){
if(vis[x] == col + 1) return;
vis[x] = col + 1;
maxn[x] = 0;
for(int i = 0;i < vec[x].size();i++){
int next = vec[x][i];
dfs(col,next);
maxn[x] = max(maxn[x],maxn[next]);
}
if(col == str[x] - 'a') maxn[x]++;
}
int largestPathValue(string colors, vector<vector<int>>& edges) {
int cnt = colors.size();
str = colors;
int fz[100005] = {0};
int bianli[100005] = {0};
for(int i = 0;i < edges.size();i++){
vec[edges[i][0]].push_back(edges[i][1]);
fz[edges[i][1]]++;
bianli[edges[i][1]]++;
}
queue<int> que;
for(int i = 0;i < colors.size();i++){
if(fz[i] == 0) que.push(i);
}
while(que.size()){
int x = que.front();
cnt--;
que.pop();
for(int i = 0;i < vec[x].size();i++){
int next = vec[x][i];
fz[next]--;
if(fz[next] == 0) que.push(next);
}
}
if(cnt != 0) return -1;
for(int i = 0;i < 26;i++){
for(int j = 0;j < colors.size();j++){
if(bianli[j] == 0){
dfs(i,j);
out = max(out,maxn[j]);
}
}
}
return out;
}
};
其实。。。。我发现广搜更简单
每次到一个点,然后更新对应26个颜色最大值,因为拓扑排序在到达某个值的时候肯定没有入度了,更新出来的值就是当前最大值
class Solution {
public:
vector<int> vec[100005];
int vis[100005] = {0};
int out = 1;
int maxn[100005][26];
int largestPathValue(string colors, vector<vector<int>>& edges) {
int cnt = colors.size();
int fz[100005] = {0};
for(int i = 0;i < edges.size();i++){
vec[edges[i][0]].push_back(edges[i][1]);
fz[edges[i][1]]++;
}
queue<int> que;
for(int i = 0;i < colors.size();i++){
if(fz[i] == 0) que.push(i);
maxn[i][colors[i] - 'a'] = 1;
}
while(que.size()){
int x = que.front();
cnt--;
que.pop();
for(int i = 0;i < vec[x].size();i++){
int next = vec[x][i];
fz[next]--;
for(int j = 0;j < 26;j++){
if(colors[next] - 'a' == j){
maxn[next][j] = max(maxn[next][j],maxn[x][j] + 1);
}
maxn[next][j] = max(maxn[next][j],maxn[x][j]);
out = max(out,maxn[next][j]);
}
if(fz[next] == 0) que.push(next);
}
}
if(cnt != 0) return -1;
return out;
}
};
。。。。这可能是我离AK周赛最近的一次