24pts 求助

P2272 [ZJOI2007] 最大半连通子图

Zhang_Wenjie @ 2024-07-27 22:33:21

#include <bits/stdc++.h>
#define re register int 

using namespace std;
const int N = 1e5 + 10, M = 1e6 + 10;

struct Edge
{
    int to, next;
}e[M];
int top, h[N];
int dfn[N], low[N], idx, scc[N], siz[N], cnt;
int in[N], f[N], g[N];
int n, m, mod, ax[N], ay[N];
bool st[N], used[N];

stack<int> stk;
vector<int> v[N];

inline void add(int x, int y)
{
    e[++ top] = (Edge){y, h[x]};
    h[x] = top;
}

void tarjan(int u)
{
    dfn[u] = low[u] = ++ idx;
    st[u] = true;
    stk.push(u);

    for (re i = h[u]; i; i = e[i].next)
    {
        int v = e[i].to;
        if (!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if (st[v])
            low[u] = min(low[u], dfn[v]);
    }

    if (dfn[u] == low[u])
    {
        cnt ++;
        int ver;
        do
        {
            ver = stk.top(); stk.pop();
            st[ver] = false;
            scc[ver] = cnt;
            siz[cnt] ++;

        }while (ver != u);
    }
}

inline void topsort()
{
    queue<int> q;
    for (re i = 1; i <= cnt; i ++)
    {
        f[i] = siz[i];
        g[i] = 1;
        if (in[i] == 0) q.push(i);
    }

    while (!q.empty())
    {
        int x = q.front(); q.pop();

        for (re i = 0; i < v[x].size(); i ++)
        {
            int y = v[x][i];

            if (used[y] == x) continue;
            used[y] = x;

            if (f[x] + siz[y] > f[y])
            {
                f[y] = f[x] + siz[y];
                g[y] = g[x];
            }
            else if (f[x] + siz[y] == f[y]) 
                g[y] = (g[y] + g[x]) % mod;

            if (-- in[y] == 0)
                q.push(y);
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    cin >> n >> m >> mod;
    for (re i = 1; i <= m; i ++)
    {
        cin >> ax[i] >> ay[i];
        add(ax[i], ay[i]);
    }
    for (re i = 1; i <= n; i ++)
        if (!dfn[i]) tarjan(i);
    for (re i = 1; i <= m; i ++)
        if (scc[ax[i]] != scc[ay[i]])
        {
            v[scc[ax[i]]].push_back(scc[ay[i]]);
            in[scc[ay[i]]] ++;
        }
    topsort();
    int mx = 0, sum = 0;

    for (re i = 1; i <= cnt; i ++) mx = max(mx, f[i]);
    for (re i = 1; i <= cnt; i ++)
        if (f[i] == mx) sum = (sum + g[i]) % mod;

    cout << mx << '\n' << sum << '\n';

    return 0;
}

|