Codeforces 919D Substring ( 拓扑排序 && DAG上的DP )

Posted rubbishes

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 919D Substring ( 拓扑排序 && DAG上的DP )相关的知识,希望对你有一定的参考价值。

题意 : 给出含有 N 个点 M 条边的图(可能不连通或者包含环),每个点都标有一个小写字母编号,然后问你有没有一条路径使得路径上重复字母个数最多的次数是多少次,例如图上有条路径的顶点标号顺序是  abcaca 那么答案就是 3 ,因为 a 出现了三次,如果答案无穷大则输出 -1

 

分析 : 

不难联想到是一个动态规划类型的题目

定义 DP[i][j] 为到达顶点 i 时字母 j 最多出现了多少次

显然如果图中有环的话就输出 -1

这也就是说如果图中不存在合法拓扑排序就说明有环

如果存在拓扑排序,那么就是一个DAG

我们可以构造出拓扑序列,然后在这个图上进行上述DP过程

状态转移方程为 dp[ i 出度顶点 ][j] = max{ dp[ i 出度顶点][j], dp[i][j] + (i 出度顶点编号 == j ? 1 : 0) }

可以使用队列构造拓扑排序,在构造的过程中完成 DP

 

技术分享图片
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;
struct EDGE{ int v, nxt; }Edge[maxn];
char ch[maxn];
int Deg[maxn];
int dp[maxn][26];
int Head[maxn], cnt;
int N, M;

inline void init()
{
    for(int i=0; i<=N; i++){
        Head[i] = -1, Deg[i] = 0;
        for(int j=0; j<26; j++)
            dp[i][j] = 0;
    }
    cnt = 0;
}

inline void AddEdge(int From, int To)
{
    Edge[cnt].v = To;
    Edge[cnt].nxt = Head[From];
    Head[From] = cnt++;
}

#define Debug 0
int main(void)
{
#if Debug
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // Debug
    while(~scanf("%d %d", &N, &M)){
        for(int i=1; i<=N; i++)
            scanf(" %c", &ch[i]);
//        for(int i=1; i<=N; i++)
//            putchar(ch[i]);
        init();
        int From, To;
        while(M--){
            scanf("%d %d", &From, &To);
            AddEdge(From, To);
            Deg[To]++;
        }

        queue<int> que;
        while(!que.empty()) que.pop();
        for(int i=1; i<=N; i++)
            if(!Deg[i]){
                que.push(i);
                dp[i][ch[i]-a] = 1;
            }

        int num = 0;
        while(!que.empty()){
            int v = que.front();
            que.pop();
            num++;
            for(int i=Head[v]; i!=-1; i=Edge[i].nxt){
                int Eiv = Edge[i].v;
                for(int j=0; j<26; j++)
                    dp[Eiv][j] = max(dp[Eiv][j], dp[v][j] + (ch[Eiv]-a == j));
                Deg[Eiv]--;
                if(!Deg[Eiv])
                    que.push(Eiv);
            }
        }
        //printf("%d\\n", num);
        if(num != N){
            puts("-1");
            continue;
        }else{
            int ans = 0;
            for(int i=1; i<=N; i++){
                for(int j=0; j<26; j++){
                    ans = max(ans, dp[i][j]);
                }
            }
            printf("%d\\n", ans);
        }
    }
    return 0;
}
View Code

 

以上是关于Codeforces 919D Substring ( 拓扑排序 && DAG上的DP )的主要内容,如果未能解决你的问题,请参考以下文章

Codefroces 919D Substring(拓扑排序+DP)

CF919D Substring

CF919D Substring (dag dp)

Codeforces Round #460 (Div. 2)

Codeforces 919 D Substring

Codeforces 919 D. Substring (记忆化搜索)