zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    C#中两数相除为0的原因
    Keil STM32F4xx_DFP.1.0.8.pack下载链接
    LabVIEW入门第九天(数组和簇)
    C#执行文件抛出异常方法
    C#中两数相除为0的原因
    C#判断文件夹路径是否存在并新建
    C#窗体程序随电脑分辨率自动调整大小
    C#判断文件夹路径是否存在并新建
    C#窗体程序随电脑分辨率自动调整大小
    VisualTreeHelper使用之ListBox模板DataTemplate中CheckBox选中项(WP7.1)
  • 原文地址:https://www.cnblogs.com/MingSD/p/8400745.html
Copyright © 2011-2022 走看看