题意 : 给出含有 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;
;
struct EDGE{ int v, nxt; }Edge[maxn];
char ch[maxn];
int Deg[maxn];
];
int Head[maxn], cnt;
int N, M;

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

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)){
        ; 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();
        ; i<=N; i++)
            if(!Deg[i]){
                que.push(i);
                dp[i][ch[i]-;
            }

        ;
        while(!que.empty()){
            int v = que.front();
            que.pop();
            num++;
            ; i=Edge[i].nxt){
                int Eiv = Edge[i].v;
                ; j<; 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{
            ;
            ; i<=N; i++){
                ; j<; j++){
                    ans = max(ans, dp[i][j]);
                }
            }
            printf("%d\n", ans);
        }
    }
    ;
}

Codeforces 919D Substring ( 拓扑排序 && DAG上的DP )的更多相关文章

  1. CodeForces - 919D Substring (拓扑排序+dp)

    题意:将一个字符串上的n个字符视作点,给出m条有向边,求图中路径上最长出现的相同字母数. 分析:首先如果这张图中有环,则可以取无限大的字符数,在求拓扑排序的同时可以确定是否存在环. 之后在拓扑排序的结 ...

  2. Codeforces 919D Substring (拓扑排序+树形dp)

    题目:Substring 题意:给你一个有向图, 一共有n个节点 , m条变, 一条路上的价值为这个路上出现过的某个字符最多出现次数, 现求这个最大价值, 如果价值可以无限大就输出-1. 题解:当这个 ...

  3. UVA - 10131Is Bigger Smarter?(DAG上的DP)

    题目:UVA - 10131Is Bigger Smarter? (DAG) 题目大意:给出一群大象的体重和IQ.要求挑选最多的大象,组成一个序列.严格的体重递增,IQ递减的序列.输出最多的大象数目和 ...

  4. Codeforces 919D Substring 【拓扑排序】+【DP】

    <题目链接> 题目大意:有一个具有n个节点,m条边的有向图,每个点对应一个小写字母,现在给出每个顶点对应的字母以及有向边的连接情况,求经过的某一条路上相同字母出现的最多次数.如果次数无限大 ...

  5. Codeforces 919D - Substring

    919D - Substring 思路: 拓扑排序判环+DAG上dp+记忆化搜索 状态:dp[i][j]表示以i为起点的路径中j的最大出现次数 初始状态:dp[i][j]=1(i have no so ...

  6. CodeForces 721C Journey(拓扑排序+DP)

    <题目链接> 题目大意:一个DAG图有n个点,m条边,走过每条边都会花费一定的时间,问你在不超过T时间的条件下,从1到n点最多能够经过几个节点. 解题分析:对这个有向图,我们进行拓扑排序, ...

  7. Codeforces 510C (拓扑排序)

    原题:http://codeforces.com/problemset/problem/510/C C. Fox And Names time limit per test:2 seconds mem ...

  8. E - E CodeForces - 1100E(拓扑排序 + 二分)

    E - E CodeForces - 1100E 一个n个节点的有向图,节点标号从1到n,存在m条单向边.每条单向边有一个权值,代表翻转其方向所需的代价.求使图变成无环图,其中翻转的最大边权值最小的方 ...

  9. CodeForces - 1100E 二分+拓扑排序

    题意: 一个n个节点的有向图,节点标号从1到n,存在m条单向边.每条单向边有一个权值,代表翻转其方向所需的代价.求使图变成无环图,其中翻转的最大边权值最小的方案,以及该方案翻转的最大的边权. Inpu ...

随机推荐

  1. JMS(Java消息服务)入门教程(一)

    什么是Java消息服务 Java消息服务指的是两个应用程序之间进行异步通信的API,它为标准消息协议和消息服务提供了一组通用接口,包括创建.发送.读取消息等,用于支持JAVA应用程序开发.在J2EE中 ...

  2. CentOS7 linux系统多种方式安装ClickHouse数据库

    clickhouse是由俄罗斯Yandex公司开发的列式存储数据库,于2016年开源,clickhouse的定位是快速的数据分析,对于处理海量数据的情况性能非常好,在网上也有很多测试的案例,在大数据的 ...

  3. Linux系统搭建并管理Git服务器

    搭建Git服务器 GitHub就是一个免费托管开源代码的远程仓库.但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓 ...

  4. 【转】mysql用sql实现split函数

    关键词:mysql split mysql根据逗号将一行数据拆分成多行数据1.原始数据演示 2.处理结果演示 3.sql语句 SELECT a.id , a.NAME , substring_inde ...

  5. spark 常用设置

    1.spark.hadoop.validateOutputSpecs 若设置为true,saveAsHadoopFile会验证输出目录是否存在.虽然设为false可直接覆盖文件路径

  6. Process进程 ProcessStartInfo.UseShellExecute 属性

    https://docs.microsoft.com/zh-cn/previous-versions/dotnet/netframework-1.1/k7z89z41(v=vs.80) 启动进程示例: ...

  7. Java 读取Json文件内容

    读取json文件为String类型: import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logge ...

  8. 利用bing图片搜索接口开发图片搜索应用程序

    概述:通过bing的图片搜索引擎,开发自己的图片搜索应用程序.bing的图片搜索接口是收费的,但是初次注册使用,key可以免费试用30天 程序运行效果如下 一,代码如下 static SearchRe ...

  9. java学习笔记(5)多线程

    一.简介(过段时间再写,多线程难度有点大) --------------------------------------- 1.进程:运行时的概念,运行的应用程序 2.线程:应用程序内部并发执行的代码 ...

  10. vue video.js使用

    插件github地址:https://github.com/videojs/video.js 这边做一个切换视频vue url的解决记录 this.$nextTick(() => { let u ...