zoukankan      html  css  js  c++  java
  • BZOJ 1093: [ZJOI2007]最大半连通子图

    二次联通门 : BZOJ 1093: [ZJOI2007]最大半连通子图

    /*
        BZOJ 1093: [ZJOI2007]最大半连通子图
    
        
        Tarjan 缩点
        Dp求最长链和方案数
        不是很懂为什么要拓扑排序,就没写,可是却过了
        注意缩点时的重边
    */
    #include <cstdio>
    #include <iostream>
    
    const int BUF = 12312312;
    char Buf[BUF], *buf = Buf;
    
    inline void read (int &now)
    {
        for (now = 0; !isdigit (*buf); ++ buf);
        for (; isdigit (*buf); now = now * 10 + *buf - '0', ++ buf);
    }
    #define Max 200004
    inline int min (int a, int b) { return a < b ? a : b; }
    int N, M, Mod, Stack[Max], top;
    struct E { E *n; int v; };
    E *list[Max], *_list[Max], poor[Max * 22], *Ta = poor;bool is[Max];
    int low[Max], dfn[Max], scc[Max], Scc, C;
    int key[Max];
    inline int max (int a, int b) { return a > b ? a :  b; }
    void Tarjan_ (int n)
    {
        dfn[n] = low[n] = ++ C; E *e;
        Stack[++ top] = n;    
        for (E *e = list[n]; e; e = e->n)
            if (!dfn[e->v])
                Tarjan_ (e->v), low[n] = min (low[n], low[e->v]);
            else if (!scc[e->v])
                low[n] = min (low[n], dfn[e->v]);    
        if (dfn[n] == low[n])
        {
            ++ Scc; int res;
            do { res = Stack[top --], scc[res] = Scc; } while (res != n);
        }
    }
    int f[Max], g[Max];
    void Dp (int n)
    {
        if (is[n]) return ; is[n] = true; E *e; f[n] = key[n];
        for (e = _list[n]; e; e = e->n)
            Dp (e->v), f[n] = max (f[n], f[e->v] + key[n]);
        for (e = _list[n]; e; e = e->n)
            if (f[n] == f[e->v] + key[n]) g[n] = (g[n] + g[e->v]) % Mod;
        if (g[n] == 0) g[n] = 1;
    }
    
    int Main ()
    {
        fread (buf, 1, BUF, stdin); read (N), read (M), read (Mod);
        register int i; int x, y; E *e, *c; int Answer = 0;
        for (i = 1; i <= M; ++ i)
        {
            read (x), read (y);
            ++ Ta, Ta->v = y, Ta->n = list[x], list[x] = Ta;
        }
        for (i = 1; i <= N; ++ i) if (!dfn[i]) Tarjan_ (i);
        for (int n = 1; n <= N; ++ n)
        {
            ++ key[scc[n]];
            for (e = list[n]; e; e = e->n)
                if (scc[n] != scc[e->v])
                {
                    for (c = _list[scc[n]]; c; c = c->n)
                        if (c->v == scc[e->v]) goto Fuck;
                    ++ Ta, Ta->v = scc[e->v], Ta->n = _list[scc[n]], _list[scc[n]] = Ta;
                    Fuck : continue;
                }
        }
        for (i = 1; i <= Scc; ++ i) if (!is[i]) Dp (i);
        for (i = 1; i <= Scc; ++ i) Answer = max (Answer, f[i]);
        int res = 0;
        for (i = 1; i <= Scc; ++ i) if (Answer == f[i]) res = (res + g[i]) % Mod;
        printf ("%d
    %d", Answer, res);
        return 0;
    }
    int ZlycerQan = Main ();
    int main (int argc, char *argv[]) {;}
  • 相关阅读:
    重载运算符 && 构造函数 的写法
    2019 ICPC Asia Xuzhou Regional
    中国剩余定理
    求逆元
    Exgcd
    Leading Robots
    大家好
    AtCoder Grand Contest 047 部分题解
    CodeForces 1389E Calendar Ambiguity 题解
    CodeForces 1380F Strange Addition 题解
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/7491412.html
Copyright © 2011-2022 走看看