手动博客搬家: 本文发表于20180716 10:53:12, 原地址https://blog.csdn.net/suncongbo/article/details/81061500

给定一个\(n\)个点\(m\)条边的有向图(不一定无环),每个点上有一个小写字母。要找一条路径,使得路径上出现次数最多的字母出现的次数最多。如果答案为无穷大输出-1.

题解:何时无穷大?有环的时候可以不停地走环,统计无限次答案,答案为无穷大。因此,对于-1的情况,只需要判一下环即可。

对于有限大的情况,令\(dp[i][c]\)表示以第\(i\)个节点结束的路径中含有\(c\)这个字母次数的最大值。则有\(dp[i][c]=\max_{j\in ind[i]}{dp[j][c]}+[a[i]==c]\), \(a[i]\)为第\(i\)个点的字母。

然后就可以得到答案了。时间复杂度\(O(mS)\), S为字符集大小26.

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int N = 3e5;
const int S = 26;
struct Edge
{
int v,nxt; bool used;
} e[N+3];
int fe[N+2];
char s[N+2];
int a[N+2];
int dfn[N+2],low[N+2];
int sta[N+2];
bool ins[N+2],vis[N+2];
int dp[N+2][S+2];
int ind[N+2];
int que[N+2];
int n,m,tp,mx,head,tail,tot; void addedge(int u,int v)
{
e[++m].v = v; e[m].nxt = fe[u]; fe[u] = m;
} void Tarjan(int u)
{
dfn[u] = low[u] = ++tp; sta[tp] = u; ins[u] = true;
for(int i=fe[u]; i; i=e[i].nxt)
{
int v = e[i].v;
if(!dfn[v]) {Tarjan(v); low[u] = min(low[v],low[u]);}
else if(ins[v]) low[u] = min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
int tmp = 1;
while(sta[tp]!=u && tp>0)
{
int v = sta[tp];
ins[v] = false;
tp--; tmp++;
}
ins[u] = false; tp--;
if(tmp>mx) mx = tmp;
}
} int main()
{
int m0; m = 0;
scanf("%d%d",&n,&m0);
scanf("%s",s+1); for(int i=1; i<=n; i++) a[i] = (int)s[i]-'a'+1;
for(int i=1; i<=m0; i++) {int x,y; scanf("%d%d",&x,&y); addedge(x,y); if(x==y) {printf("-1\n"); return 0;}}
for(int i=1; i<=n; i++) {if(!dfn[i]) Tarjan(i);}
if(mx>1) {printf("-1\n"); return 0;}
for(int i=1; i<=n; i++)
{
for(int j=fe[i]; j; j=e[j].nxt) ind[e[j].v]++;
}
tot = 0;
for(int i=1; i<=n; i++) dp[i][a[i]] = 1;
while(tot<n)
{
for(int j=1; j<=n; j++)
{
if(ind[j]==0 && vis[j]==false)
{
tail++;
que[head] = j; vis[j] = true; tot++;
while(head<=tail)
{
int c = que[head++];
for(int i=fe[c]; i; i=e[i].nxt)
{
if(e[i].used) continue;
e[i].used = true;
ind[e[i].v]--;
for(int k=1; k<=S; k++)
{
if(a[e[i].v]==k) dp[e[i].v][k] = max(dp[e[i].v][k],dp[c][k]+1);
else dp[e[i].v][k] = max(dp[e[i].v][k],dp[c][k]);
}
if(ind[e[i].v]==0 && vis[e[i].v]==false)
{
vis[e[i].v] = true; tot++;
que[++tail] = e[i].v;
}
}
}
}
}
}
int ans = 0;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=S; j++) ans = max(ans,dp[i][j]);
}
printf("%d\n",ans);
return 0;
}

Codeforces 919D Substring (拓扑图DP)的更多相关文章

  1. Codeforces 919D - Substring

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

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

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

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

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

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

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

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

    题意 : 给出含有 N 个点 M 条边的图(可能不连通或者包含环),每个点都标有一个小写字母编号,然后问你有没有一条路径使得路径上重复字母个数最多的次数是多少次,例如图上有条路径的顶点标号顺序是  a ...

  6. 微软2016校园招聘在线笔试 B Professor Q's Software [ 拓扑图dp ]

    传送门 题目2 : Professor Q's Software 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Professor Q develops a new s ...

  7. [Codeforces 1201D]Treasure Hunting(DP)

    [Codeforces 1201D]Treasure Hunting(DP) 题面 有一个n*m的方格,方格上有k个宝藏,一个人从(1,1)出发,可以向左或者向右走,但不能向下走.给出q个列,在这些列 ...

  8. Codeforces 919D:Substring(拓扑排序+DP)

    D. Substring time limit: per test3 seconds memory limit: per test256 megabytes inputstandard: input ...

  9. CodeForces 163A Substring and Subsequence dp

    A. Substring and Subsequence 题目连接: http://codeforces.com/contest/163/problem/A Description One day P ...

随机推荐

  1. [Java]LeetCode57 Insert Interval

    Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessa ...

  2. 哈理工2015暑假集训 zoj 2975 Kinds of Fuwas

    G - Kinds of Fuwas Time Limit:2000MS    Memory Limit:65536KB    64bit IO Format:%lld & %llu Subm ...

  3. C++源码实现:21种常用设计模式

    C++源码实现:21种常用设计模式一直以来在设计模式的学习中,都是出现java的源码,这对学习C++的极度不友好.本工程是基于C++实现21种常用的设计模式,里面包含了实例代码和示例.编写的时候在学习 ...

  4. Android EditText得到和失去焦点时,自定义处理内容

    当android的Edittext得到/失去焦点时,需要自定义一些处理内容时,需要对EditText对象的Focus进行监听处理. 在Activity中,做以下处理: 1.取得EditText对象. ...

  5. Java 错误:找不到或无法加载主类(源文件中含有包名 package)

    1. 问题定位 编译(javac)和执行(java)java 程序时,出现这种类型的错误:找不到或无法加载主类: 首先排除是否是环境变量配置不当造成的问题,只要保证,命令行界面能够识别 javac/j ...

  6. Java-java-com-util-common-service:ServiceException.java

    ylbtech-Java-java-com-util-common-service:ServiceException.java 1.返回顶部 1. package com.shineyoo.manag ...

  7. UIDynamicBehavior的简单使用:接球小游戏

    一.概念扩充: 1.在开发中,我们可以使用UIKit中提供的仿真行为,实现与现实生活中类似的物理仿真动画,UIKit动力学最大的特点是将现实世界动力驱动的动画引入了UIKit,比如重力,铰链连接,碰撞 ...

  8. Tunnel Warfare(树状数组+二分)

    http://poj.org/problem?id=2892 题意:输入n,m.n代表数轴的长度,m代表操作数. D x: 摧毁点x Q x: 询问村庄x最左与最右没有被摧毁的点的距离 R  :恢复最 ...

  9. Your configuration specifies to merge with the ref 'refs/heads/v.autoCheckProduct.20190325' from the remote, but no such ref was fetched.

    问题: 创建新的分支,当我们执行git pull,出现如下错误 解决办法: 1.切换到主分支(或者被依赖的分支,也就是你从哪个分支上拉取新的分支),博主这里是master分支 2.执行以下两个命令 3 ...

  10. python 10:len(list)(获取列表长度)以及负访问性

    bicycles = ['trek', 'cannondale', 'redline', 'specialized'] print(len(bicycles)) #获取某列表长度,即列表元素个数 pr ...