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

Posted Schenker

tags:

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

题目:Substring

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

题解:当这个有向图构成一个环的时候就会使得值无限大,所以先用拓扑排序判断一下有没有环,如果有环直接输出-1, 如果没有环就再使用树形dp并记忆化存数,来找到最大值。

代码:

 1 #include<cstring>
 2 #include<iostream>
 3 using namespace std;
 4 const int N = 300000+5;
 5 string str;
 6 int head[N], c[N], topo[N], dp[N][26];
 7 int cnt = 0, n, m, k, ans = 0;
 8 struct Node
 9 {
10     int nx;
11     int to;
12 }Edge[N];
13 void add_edge(int u, int v)
14 {
15     Edge[cnt].to = v;
16     Edge[cnt].nx = head[u];
17     head[u] = cnt++;
18 }
19 bool dfs(int u)
20 {
21     c[u] = -1;
22     for(int i = head[u]; ~i; i = Edge[i].nx)
23     {
24         int v = Edge[i].to;
25         if(c[v] < 0) return false;
26         else if(!c[v] && !dfs(v)) return false;
27     }
28     c[u] = 1;
29     topo[--k] = u;
30     return true;
31 }
32 bool topo_sort()
33 {
34     k = n;
35     memset(c, 0, sizeof(c));
36     for(int i = 0; i < n; i++)
37     {
38         if(!c[i])
39             if(!dfs(i)) return false;
40     }
41     return true;
42 }
43 void dfs_count(int u)
44 {
45     c[u] = 1;
46     for(int i = head[u]; ~i; i = Edge[i].nx)
47     {
48         int v = Edge[i].to;
49         if(!c[v]) dfs_count(v);
50         for(int i = 0; i < 26; i++)
51         {
52             if(dp[u][i] < dp[v][i])
53             {
54                 dp[u][i] = dp[v][i];
55                 int tmp  = (str[u]-a == i)? dp[u][i]+1 : dp[u][i];
56                 if(tmp > ans) ans = tmp;
57             }
58         }
59     }
60     dp[u][str[u]-a]++;
61 }
62 int main()
63 {
64     ios::sync_with_stdio(false);
65     cin.tie(0);
66     memset(head, -1, sizeof(head));
67     cin >> n >> m;
68     cin >> str;
69     int u, v;
70     for(int i = 1; i <= m; i++)
71     {
72         cin >> u >> v;
73         add_edge(u-1, v-1);
74     }
75     if(!topo_sort())
76     {
77         cout << -1 << endl;
78         return 0;
79     }
80     memset(c, 0, sizeof(c));
81     for(int i = 0; i < n; i++)
82     {
83         if(!c[topo[i]])
84             dfs_count(topo[i]);
85     }
86     cout << ans << endl;
87 }

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

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

CF919D Substring

CF919D Substring (dag dp)

Codeforces Round #460 (Div. 2)

Codeforces 919 D Substring

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