LeetCode #1857 有向图中最大颜色值

1857. 有向图中最大颜色值

给你一个 有向图 ,它含有 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周赛最近的一次

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值