• 【tarjan缩点+分层图】草鉴定Grass Cownoisseur


    P3119 [USACO15JAN] 草鉴定Grass Cownoisseur

    tarjan缩点+建分层图

    缩点:单向边+可重复走一个牧场

    缩完点后, 对于不在原图中的一条边(u, v),  if(sd[u] != sd[v]) 连边, 建立新图编号为1~tot//sd[] 该点属于哪个强连通分量, tot是强连通的数量

    分层图:可逆向走一次,分层图顶点编号为 tot+1 ~ 2 * n;对于缩点后新图中的一条边(u, v), 将该边终点与分层图的起点连边, 达到逆向走一次的目的add(v, u+tot)

    分层图自身也要连边, 对于缩点后的新图(u, v) , 分层图连相应的边add(u+tot, v+tot)

    记得分层图上的点权值与缩点后新图权值相同!!

    因为最后会走回1号点,会加上1号点所在强连通的权值, 所以开始初始dis只可以为0

    自信代码姹紫嫣红竟因忘删注释?!数组开的正好re两个点, 开大十倍就好了QAQ

     1 #include<queue>
     2 #include<cstdio>
     3 #include<iostream>
     4 using namespace std;
     5 const int sz = 1000010;
     6 int n, m, tim = 0, top = 0, num = 0, num2 = 0, tot = 0;
     7 int h[sz], dfn[sz], low[sz], sta[sz], x[sz], y[sz], sd[sz];
     8 int h2[sz], dis[sz ], node[sz];
     9 bool vis[sz], book[sz ];
    10 struct Egde {
    11     int nxt, to, dis;
    12 }e[sz], e2[sz << 1];
    13 int read() {
    14     char ch = getchar(); int x = 0, f = 1;
    15     while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    16     while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    17     return x * f;
    18 }
    19 void add(int from, int to) {
    20     e[++num].nxt = h[from];
    21     e[num].to = to;
    22     h[from] = num;
    23 }
    24 void add2(int from, int to) {
    25     e2[++num2].nxt = h2[from];
    26     e2[num2].to = to;
    27      h2[from] = num2;
    28 }
    29 void tarjan(int u) {
    30     low[u] = dfn[u] = ++tim;
    31     sta[++top] = u;
    32     vis[u] = 1;
    33     for(int i = h[u]; i; i = e[i].nxt) {
    34         int v = e[i].to;
    35         if(!dfn[v]) {
    36             tarjan(v);
    37             low[u] = min(low[v], low[u]);
    38         }
    39         else if(vis[v]) low[u] = min(low[u], dfn[v]);
    40     }
    41     if(dfn[u] == low[u]) {
    42             tot++;
    43         while(u != sta[top+1]) {
    44             sd[sta[top]] = tot;
    45             node[tot]++;
    46             vis[sta[top]] = 0;
    47             top--;
    48         }
    49     }
    50 }
    51 void spfa(int s) {
    52     queue<int>q;
    53     for(int i = 1; i <= (n<<1); i++) {
    54         dis[i] = 0;
    55         book[i] = 0;
    56     }
    57     book[s] = 1;
    58     q.push(s);
    59     while(!q.empty()) {
    60         int u = q.front();
    61         q.pop();
    62         book[u] = 0;
    63         for(int i = h2[u]; i; i = e2[i].nxt) {
    64             int v = e2[i].to;
    65             if(dis[v] < dis[u] + node[v]) {
    66                 dis[v] = dis[u] + node[v];
    67                 if(!book[v]) {
    68                     book[v] = 1;
    69                     q.push(v);
    70                 }
    71             }
    72         }
    73     }
    74 }
    75 int main() {
    76     scanf("%d%d", &n, &m);
    77     for(int i = 1; i <= m; i++) {
    78         x[i] = read(), y[i] = read();
    79         add(x[i], y[i]);
    80     }    
    81     for(int i = 1; i <= n; i++)
    82         if(!dfn[i]) tarjan(i);
    83     for(int i = 1; i <= m; i++) {
    84         int u = sd[x[i]], v = sd[y[i]];
    85         if(u != v) {
    86             add2(u, v);
    87             add2(v, u+tot);
    88             add2(u+tot, v+tot);
    89         }    
    90     }
    91     for(int i=1;i<=tot;i++) node[i+tot]=node[i];
    92     spfa(sd[1]);
    93     printf("%d", dis[sd[1]+tot]);
    94     return 0;
    95 }

    和aq重学了个缩点QAQ

  • 相关阅读:
    预备知识
    开场白
    H.264 / MPEG-4 Part 10 White Paper-翻译
    H.264简介
    batchGetAnchorLevel(dubbo接口)
    【Python022--递归】
    【python021-函数lambda表达式】
    【Python020--内嵌函数和闭包】
    【Python019--函数与过程】
    【python018--函数参数】
  • 原文地址:https://www.cnblogs.com/Hwjia/p/9896389.html
Copyright © 2020-2023  润新知