列表

详情


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 有一个环。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int largestPathValue(string colors, vector<vector<int>>& edges) { } };

java 解法, 执行用时: 63 ms, 内存消耗: 116.5 MB, 提交时间: 2023-09-23 11:14:35

class Solution {
    public int largestPathValue(String colors, int[][] edges) {
        int n = colors.length(), ans = 0;
        List<List<Integer>> graph = new ArrayList<>(n);
        for (int i = 0; i < n; ++i) graph.add(new ArrayList<>());
        int[] degree = new int[n];
        for (int[] edge : edges) {
            graph.get(edge[0]).add(edge[1]);
            ++degree[edge[1]];
        }
        Queue<Integer> queue = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) if (degree[i] == 0) queue.offer(i);
        int[][] dp = new int[n][26];
        while (!queue.isEmpty()) {
            int u = queue.poll();
            ++dp[u][colors.charAt(u) - 'a'];
            --n;
            if (graph.get(u).isEmpty()) {
                for (int c = 0; c < 26; ++c) ans = Math.max(ans, dp[u][c]);
                continue;
            }
            for (int v : graph.get(u)) {
                for (int c = 0; c < 26; ++c) dp[v][c] = Math.max(dp[v][c], dp[u][c]);
                if (--degree[v] == 0) queue.offer(v);
            }
        }
        return n == 0 ? ans : -1;
    }
}

python3 解法, 执行用时: 2220 ms, 内存消耗: 81.5 MB, 提交时间: 2023-09-23 11:14:12

class Solution:
    def largestPathValue(self, colors: str, edges: List[List[int]]) -> int:
        n = len(colors)
        # 邻接表
        g = collections.defaultdict(list)
        # 节点的入度统计,用于找出拓扑排序中最开始的节点
        indeg = [0] * n

        for x, y in edges:
            indeg[y] += 1
            g[x].append(y)
        
        # 记录拓扑排序过程中遇到的节点个数
        # 如果最终 found 的值不为 n,说明图中存在环
        found = 0
        f = [[0] * 26 for _ in range(n)]
        q = collections.deque()
        for i in range(n):
            if indeg[i] == 0:
                q.append(i)
    
        while q:
            found += 1
            u = q.popleft()
            # 将节点 u 对应的颜色增加 1
            f[u][ord(colors[u]) - ord("a")] += 1
            # 枚举 u 的后继节点 v
            for v in g[u]:
                indeg[v] -= 1
                # 将 f(v,c) 更新为其与 f(u,c) 的较大值
                for c in range(26):
                    f[v][c] = max(f[v][c], f[u][c])
                if indeg[v] == 0:
                    q.append(v)
        
        if found != n:
            return -1
        
        ans = 0
        for i in range(n):
            ans = max(ans, max(f[i]))
        return ans

cpp 解法, 执行用时: 524 ms, 内存消耗: 140.1 MB, 提交时间: 2023-09-23 11:13:57

class Solution {
public:
    int largestPathValue(string colors, vector<vector<int>>& edges) {
        int n = colors.size();
        // 邻接表
        vector<vector<int>> g(n);
        // 节点的入度统计,用于找出拓扑排序中最开始的节点
        vector<int> indeg(n);
        for (auto&& edge: edges) {
            ++indeg[edge[1]];
            g[edge[0]].push_back(edge[1]);
        }
        
        // 记录拓扑排序过程中遇到的节点个数
        // 如果最终 found 的值不为 n,说明图中存在环
        int found = 0;
        vector<array<int, 26>> f(n);
        queue<int> q;
        for (int i = 0; i < n; ++i) {
            if (!indeg[i]) {
                q.push(i);
            }
        }
        
        while (!q.empty()) {
            ++found;
            int u = q.front();
            q.pop();
            // 将节点 u 对应的颜色增加 1
            ++f[u][colors[u] - 'a'];
            // 枚举 u 的后继节点 v
            for (int v: g[u]) {
                --indeg[v];
                // 将 f(v,c) 更新为其与 f(u,c) 的较大值
                for (int c = 0; c < 26; ++c) {
                    f[v][c] = max(f[v][c], f[u][c]);
                }
                if (!indeg[v]) {
                    q.push(v);
                }
            }
        }

        if (found != n) {
            return -1;
        }
        
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans = max(ans, *max_element(f[i].begin(), f[i].end()));
        }
        return ans;
    }
};

golang 解法, 执行用时: 208 ms, 内存消耗: 51.1 MB, 提交时间: 2023-09-23 11:13:36

// 按照拓扑序 DP
func largestPathValue(colors string, edges [][]int) (ans int) {
	n := len(colors)
	g := make([][]int, n)
	deg := make([]int, n)
	for _, e := range edges {
		v, w := e[0], e[1]
		if v == w {
			return -1
		}
		g[v] = append(g[v], w)
		deg[w]++
	}
	cnt := 0
	dp := make([][26]int, n)
	q := []int{}
	for i, d := range deg {
		if d == 0 {
			q = append(q, i)
		}
	}
	for len(q) > 0 {
		v := q[0]
		q = q[1:]
		cnt++
		dp[v][colors[v]-'a']++
		ans = max(ans, dp[v][colors[v]-'a'])
		for _, w := range g[v] {
			for i, c := range dp[v] {
				dp[w][i] = max(dp[w][i], c)
			}
			if deg[w]--; deg[w] == 0 {
				q = append(q, w)
			}
		}
	}
	if cnt < n {
		return -1
	}
	return
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

上一题