码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2018-02-08 20:04:57      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:fine   body   class   freopen   http   push   www   har   动态   

题意 : 给出含有 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 )

标签:fine   body   class   freopen   http   push   www   har   动态   

原文地址:https://www.cnblogs.com/Rubbishes/p/8432509.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!