Loading

CodeForces-919D Substring DP,拓扑排序

给定一个有 n 个节点和 m 条有向边的图。每个节点上有一个小写字母。

我们将路径的值定义为最经常出现的字母的数目。例如,如果路径上的字母是 “abaca”,那么该路径的值是 3

你的任务是找到一条值最大的路径,并将这条路径的值输出。

 

显然条件是必须在一条路径上,容易想到限制要求拓扑排序,因此可以在拓扑序上DP

dp[i][j]表示前i个点中,字母j出现的次数。

int n, m, u, v;
int num;
queue<int> q;
int dp[300005][27];
int Indeg[300005];
char s[300005];
vector<int> vec[300005];

bool topo() {
    while (!q.empty()) q.pop();
    num = 0;
    for (int i = 1; i <= n; i++) if (!Indeg[i]) {
        q.push(i);
        dp[i][s[i] - 'a']++;
    }
    while (!q.empty()) {
        int now = q.front();
        q.pop();
        num++;
        for (int i = 0; i < vec[now].size(); i++) {
            if (--Indeg[vec[now][i]] == 0) {
                q.push(vec[now][i]);
            }
            for (int j = 0; j < 26; j++) {
                dp[vec[now][i]][j] = max(dp[vec[now][i]][j], dp[now][j] + (s[vec[now][i]] - 'a' == j));
            }
        }
    }
    if (n == num) return true;
    else return false;
}

int main() {
    n = readint();
    m = readint();
    scanf("%s", s + 1);
    for (int i = 0; i < m; i++) {
        int x = readint();
        int y = readint();
        vec[x].push_back(y);
        Indeg[y]++;
    }
    if (!topo()) puts("-1");
    else {
        int Max = -1;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < 26; j++) {
                Max = max(Max, dp[i][j]);
            }
        }
        Put(Max);
    }
}

 

posted @ 2020-08-18 21:36  MQFLLY  阅读(140)  评论(0编辑  收藏  举报