zoukankan      html  css  js  c++  java
  • Luogu P43916 图的遍历

    我们把“u点能够到达的最大点”转化为反向图中能到达u点的所有点里的最大值,可知缩点后满足无后效性。val[i]的初值设为连通分量i中的最大点。反向存图,tarjan缩点,拓扑序dp即可。

    1. #include <iostream>  
    2. #include <cstdio>  
    3. #include <queue>  
    4. #define maxn 100100  
    5. using namespace std;   
    6. int n, m;  
    7. void read(int &x) {  
    8.     x = 0;  
    9.     char ch = getchar();  
    10.     while (!isdigit(ch))  
    11.         ch = getchar();  
    12.     while (isdigit(ch))  
    13.         x = x * 10 + (ch ^ 48),  
    14.         ch = getchar();  
    15.     return;  
    16. }  
    17. struct E {  
    18.     int to, nxt;  
    19. } edge[maxn], edge2[maxn];  
    20. int head[maxn], top, head2[maxn], top2;  
    21. inline void insert(int u, int v) {  
    22.     edge[++top] = (E) {v, head[u]};  
    23.     head[u] = top;  
    24. }  
    25. inline void insert2(int u, int v) {  
    26.     edge2[++top2] = (E) {v, head2[u]};  
    27.     head2[u] = top2;  
    28. }  
    29. int low[maxn], dfn[maxn], timer, c[maxn], cnt, sta[maxn], stp;  
    30. bool ins[maxn];  
    31. int val[maxn];  
    32. void tarjan(int u) {  
    33.     low[u] = dfn[u] = ++ timer;  
    34.     sta[++stp] = u, ins[u] = true;  
    35.     for (int i = head[u]; i; i = edge[i].nxt) {  
    36.         int v = edge[i].to;  
    37.         if (!dfn[v]) {  
    38.             tarjan(v);  
    39.             low[u] = min(low[u], low[v]);  
    40.         } else if (ins[v])  
    41.             low[u] = min(low[u], dfn[v]);  
    42.     }  
    43.     if (dfn[u] == low[u]) {  
    44.         ++cnt;  
    45.         int x;  
    46.         do {  
    47.             x = sta[stp--];  
    48.             ins[x] = false;  
    49.             c[x] = cnt;  
    50.             val[cnt] = max(val[cnt], x);  
    51.         } while (x != u);  
    52.     }  
    53. }  
    54. int ind[maxn];  
    55. void build() {  
    56.     for (int u = 1; u <= n; ++u)  
    57.         for (int i = head[u]; i; i = edge[i].nxt) {  
    58.             int v = edge[i].to;  
    59.             if (c[u] != c[v])  
    60.                 insert2(c[u], c[v]), ++ind[c[v]];  
    61.         }  
    62. }  
    63. void dp() {  
    64.     queue<int> que;  
    65.     for (int i = 1; i <= cnt; ++i)  
    66.         if (!ind[i]) que.push(i);  
    67.     while (!que.empty()) {  
    68.         int u = que.front(); que.pop();  
    69.         for (int i = head2[u]; i; i = edge2[i].nxt) {  
    70.             int v = edge2[i].to;  
    71.             val[v] = max(val[v], val[u]);  
    72.             --ind[v];  
    73.             if (!ind[v])  
    74.                 que.push(v);  
    75.         }  
    76.     }  
    77.     return;  
    78. }  
    79. int main() {  
    80.     read(n), read(m);  
    81.     int u, v;  
    82.     for (int i = 1; i <= m; ++i) {  
    83.         read(u), read(v);  
    84.         insert(v, u);  
    85.     }  
    86.     for (int i = 1; i <= n; ++i)  
    87.         if (!dfn[i])  
    88.             tarjan(i);  
    89.     build();  
    90.     dp();  
    91.     for (int i = 1; i <= n; ++i)  
    92.         printf("%d ", val[c[i]]);  
    93.     return 0;  
    94. }  

    至此luogu上真哥留下的缩点习题全部完成。晚上更新对最小树形图(朱刘算法)的理解。

  • 相关阅读:
    定时器
    js中script的上下放置区别 , Dom的增删改创建
    函数声明与应用
    常规选择器
    表格的制作
    流程控制
    For循环
    洛谷P1419寻找段落
    洛谷P1021邮票面值设计
    洛谷P3119草鉴定
  • 原文地址:https://www.cnblogs.com/TY02/p/11119893.html
Copyright © 2011-2022 走看看