每日一题
搜索
dp
图论
拓扑排序
leetcode 1857
使用拓扑排序查看是否有环,如果有环就返回-1
注意点
- 拓扑排序中的indegree[x]–应该是每一个出度。
- 判断拓扑应该使用cnt == n?如果有环cnt < n,就是没有一个拓扑序列。
另外本题使用动态规划进行解决了涂色问题,
dp[v][j] = max(dp[v][j], dp[u][j] + (colors[v] == j)) v是以u为弧头的弧尾
这个公式在题目中可以在出队的时候dp[u][j]++简化
dp[v][j] = max(dp[u][j], dp[v][j])
class Solution {
public:
int largestPathValue(string colors, vector<vector<int>>& edges) {
int n = colors.size(), num = 0, ans = 0;
vector<vector<int>>g(n);
vector<int>indegree(n, 0);
vector<vector<int>>dp(n, vector<int>(26, 0));
queue<int>que;
for(auto& edge:edges) {
// printf("edges[i][0] = %d\n", edges[i][0]);
indegree[edge[1]]++;
g[edge[0]].push_back(edge[1]);
}
// printf("为\n");
for(int i = 0; i < n; i++) {
if(indegree[i] == 0){
dp[i][colors[i]-'a'] = 1;
que.push(i);
}
}
while(!que.empty()) {
num++;
int x = que.front();que.pop();
// printf("x = %d\n", x);
// dp[x][colors[x] - 'a']++;
//更新本行相连的节点
for(int v: g[x]) {
//更新每一个颜色
for(int i = 0; i < 26; i++) {
dp[v][i] = max(dp[v][i], dp[x][i] + (colors[v] - 'a' == i));
}
//更新每个节点的入度
if(--indegree[v] == 0) que.push(v);
}
}
if(num != n) return -1;
//printf("dp:\n");
for(int i = 0; i < n; i++) {
ans = max(ans, *max_element(dp[i].begin(), dp[i].end()));
}
return ans;
}
};
网络流
最短路径
数据结构
树状数组
//测试树状数组
class Tarr {
public:
int n;
vector<int>a; //从1开始
vector<int>c;
Tarr(int n, vector<int>a) {
this->n = n;
this->a = a;
c = vector<int>(n*5, 0);
for(int i = 1; i <= n; i++) {
this->update(i, a[i]-a[i-1]);
}
}
int lower_bit(int x) {
return x & (-x);
}
void update(int i, int k) {
while(i <= n) {
c[i] += k;
i += lower_bit(i);
//printf("i = %d", i);
}
}
int getsum(int i) {
int res = 0;
while(i > 0) {
res += c[i];
i -= lower_bit(i);
}
return res;
}
};
void testT(){
vector<int>a;
for(int i = 0; i < 10; i++) {
a.push_back(i);
}
Tarr t(10, a);
for(int i = 0; i < 10; i++) {
printf("pos_%d = %d\n", i, t.getsum(i));
}
printf("0-2增加1\n");
//[0,2] 加上1
t.update(1, 1);
t.update(4, -1);
for(int i = 0; i < 10; i++) {
printf("pos_%d = %d\n", i, t.getsum(i));
}
}