手动博客搬家: 本文发表于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. 使用Pods和自定义静态库实现多工程联编

    使用Pods和自定义静态库实现多工程联编 字数607 阅读112 评论0 喜欢0 近来随着公司项目开发的深入,项目的规范也就越来越高了,为了更加方便的管理自定义静态库与pods之间的联系,好好的研究了 ...

  2. CF555B Case of Fugitive

    题目大意 有一些不相交线段和一些桥,桥可以架在两个相邻的线段上.求现有的桥是否可以使所有线段连通. 题解 在两个线段上架桥,桥的长度在一个范围内,相当于一个长度的区间,一个桥只有一个长度,相当于一个长 ...

  3. Androlid入门之文件系统操作(三)文件读写

         import java.io.*; import android.app.Activity; import android.os.Bundle; import android.view.Vi ...

  4. tflearn mnist 使用MLP 全连接网络一般都会加dropout哇

    # -*- coding: utf-8 -*- """ Deep Neural Network for MNIST dataset classification task ...

  5. Spark深入之RDD

    目录 Part III. Low-Level APIs Resilient Distributed Datasets (RDDs) 1.介绍 2.RDD代码 3.KV RDD 4.RDD Join A ...

  6. vs code golang代码自动补全

    “go.useCodeSnippetsOnFunctionSuggest”: true 文件-->首选项--->设置--->用户设置 添加下行:然后就可以自动补全了,包括() “go ...

  7. PCB Genesis原点坐标转换关系

    一.Genesis原点坐标转换关系: 1.读取Genesis坐标转换:   UI界面坐标 = 文件坐标 - 偏移值 2.写入Genesis坐标转换:   文件坐标 = UI界面坐标 + 偏移值 3.为 ...

  8. A simple problem(并查集判环)

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2497 题意:给定一些点和边的关系,判断S点是否 ...

  9. Chrome 最小化恢复之后部分黑屏

    解决办法:设置->显示高级设置->关闭硬件加速

  10. Oracle_备份整库

    @echo off color 0b & cls echo echo 设置备份文件存放文件夹... echo set "tbuf=C:\OracleBackup" if n ...