cf 919D Substring

一 原题

                                                             D. Substring

time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given a graph with n nodes and m directed edges. One lowercase letter is assigned to each node. We define a path's value as the number of the most frequently occurring letter. For example, if letters on a path are "abaca", then the value of that path is 3. Your task is find a path whose value is the largest.

Input

The first line contains two positive integers n, m (1 ≤ n, m ≤ 300 000), denoting that the graph has n nodes and m directed edges.

The second line contains a string s with only lowercase English letters. The i-th character is the letter assigned to the i-th node.

Then m lines follow. Each line contains two integers x, y (1 ≤ x, y ≤ n), describing a directed edge from x to y. Note that x can be equal to y and there can be multiple edges between x and y. Also the graph can be not connected.

Output

Output a single line with a single integer denoting the largest value. If the value can be arbitrarily large, output -1 instead.

Examples
input
5 4
abaca
1 2
1 3
3 4
4 5
output
3
input
6 6
xzyabc
1 2
3 1
2 3
5 4
4 3
6 4
output
-1
input
10 14
xzyzyzyzqx
1 2
2 4
3 5
4 5
2 6
6 8
6 5
2 10
3 9
10 9
4 6
1 10
2 8
3 7
output
4
Note

In the first sample, the path with largest value is 1 → 3 → 4 → 5. The value is 3 because the letter 'a' appears 3 times.


二 分析

DFS判断是否有环,如果有环,那么输出-1。如果没有环,那么DFS后得到原图的一个拓扑排序,对于任意一条图上的路径(v1->v2->v3...),在拓扑排序中保证v_i在v_i+1之前,那么我们就可以动归得到每个点作为起点时,某个字母最多出现多少次。下面两份代码,一份是DFS,一份是裸的拓扑排序。复杂度:O(26*(n+m))


三 代码

/*
PROB: cf 919D
LANG: c++
AUTHOR: maxkibble
*/

#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;

// #define local
#define pb push_back
#define mp make_pair
#define pii pair<int, int>

const int maxn = 3e5 + 10;

int n, m, s, e, ans = 1, dp[maxn];
char ch[maxn];
bool in[maxn], vis[maxn];
vector<int> edge[maxn], seq;

bool circle(int x) {
    bool ret = false;
    in[x] = vis[x] = true;
    for(auto nxt: edge[x]) {
        if(in[nxt]) {
            ret = true;
            break;
        }
        if(!vis[nxt] && circle(nxt)) {
            ret = true;
            break;
        }
    }
    in[x] = false;
    seq.pb(x);
    return ret;
}

int main() {
    #ifdef local
        freopen("d.in", "r", stdin);
    #endif
    scanf("%d%d%s", &n, &m, ch + 1);
    for(int i = 0; i < m; i++) {
        scanf("%d%d", &s, &e);
        edge[s].pb(e);
    }
    for(int i = 1; i <= n; i++) {
        if(vis[i]) continue;
        if(circle(i)) {
            puts("-1");
            return 0;
        }
    }
    for(char c = 'a'; c <= 'z'; c++) {
        for(int i = 0; i < seq.size(); i++) {
            int v = seq[i];
            int flag = (ch[v] == c);
            dp[v] = flag;
            for(auto nxt: edge[v]) {
                dp[v] = max(dp[v], dp[nxt] + flag);
            }
            ans = max(ans, dp[v]);
        }
    }
    printf("%d\n", ans);
    return 0;
}
/*
PROB: cf 919D
LANG: c++
AUTHOR: maxkibble
*/

#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;

// #define local
#define pb push_back
#define mp make_pair
#define pii pair<int, int>

const int maxn = 3e5 + 10;

int n, m, s, e, ans = 1, degree[maxn], dp[maxn];
char ch[maxn];
queue<int> q;
vector<int> edge[maxn], seq;

void topSort() {
    for(int i = 1; i <= n; i++) {
        for(auto nxt: edge[i])
            degree[nxt]++;
    }
    for(int i = 1; i <= n; i++) {
        if(degree[i] == 0)
            q.push(i);
    }
    while(!q.empty()) {
        int u = q.front();
        seq.pb(u);
        q.pop();
        for(auto v: edge[u]) {
            degree[v]--;
            if(degree[v] == 0)
                q.push(v);
        }
    }
}

int main() {
    #ifdef local
        freopen("d.in", "r", stdin);
    #endif
    scanf("%d%d%s", &n, &m, ch + 1);
    for(int i = 0; i < m; i++) {
        scanf("%d%d", &s, &e);
        edge[s].pb(e);
    }
    
    topSort();

    if(seq.size() != n) {
        puts("-1");
        return 0;
    }

    for(char c = 'a'; c <= 'z'; c++) {
        for(int i = n - 1; i >= 0; i--) {
            int v = seq[i];
            int flag = (ch[v] == c);
            dp[v] = flag;
            for(auto nxt: edge[v]) {
                dp[v] = max(dp[v], dp[nxt] + flag);
            }
            ans = max(ans, dp[v]);
        }
    }
    printf("%d\n", ans);
    return 0;
}



猜你喜欢

转载自blog.csdn.net/max_kibble/article/details/79223415
今日推荐