BZOJ 1093 强连通缩点+DAG拓扑DP

缩点后在一个DAG上求最长点权链 和方案数

注意转移条件和转移状态

            if (nowmaxn[x] > nowmaxn[v]) {
                ans[v] = ans[x];
                nowmaxn[v] = nowmaxn[x];
            } else if (nowmaxn[x] == nowmaxn[v]) {
                ans[v] = (ans[v] + ans[x]) % X;
            }
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 100005;
const int MAXM = 1000005;
int deep, colorsum = 0;
int top;/*sta目前的大小*/
int dfn[MAXN], color[MAXN], low[MAXN];
int sta[MAXN];//存着当前所有可能能构成强连通分量的点
bool visit[MAXN];//表示一个点目前是否在sta中
int cnt[MAXN];//各个强连通分量中含点的数目
int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], ed = 1;
inline void addedge(int u, int v)
{
    to[++ed] = v;
    nxt[ed] = Head[u];
    Head[u] = ed;
}
void tarjan(int x)
{
    dfn[x] = ++deep;
    low[x] = deep;
    visit[x] = 1;
    sta[++top] = x;
    for (int i = Head[x]; i; i = nxt[i]) {
        int v = to[i];
        if (!dfn[v]) {
            tarjan(v);
            low[x] = min(low[x], low[v]);
        } else {
            if (visit[v]) {
                low[x] = min(low[x], low[v]);
            }
        }
    }
    if (dfn[x] == low[x]) {
        color[x] = ++colorsum;
        visit[x] = 0;
        while (sta[top] != x) {
            color[sta[top]] = colorsum;
            visit[sta[top--]] = 0;
        }
        top--;
    }
}
int X;
int du[MAXN];
vector<int> g[MAXN];
map<pair<int, int>, int> mp, mp2;
queue<int> que;
int ans[MAXN];
int nowmaxn[MAXN];
int main()
{
    int n, m;
    int u, v;
    scanf("%d %d %d", &n, &m, &X);
    for (int i = 1; i <= m; i++) {
        scanf("%d %d", &u, &v);
        if (!mp2[make_pair(u, v)]) {
            addedge(u, v);
            mp2[make_pair(u, v)] = 1;
        }
    }
    for (int i = 1; i <= n; i++) {
        if (!dfn[i]) {
            tarjan(i);
        }
        cnt[color[i]]++;
    }
    for (u = 1; u <= n; u++) {
        int x = color[u];
        for (int i = Head[u]; i; i = nxt[i]) {
            v = to[i];
            int y = color[v];
            if (x != y) {
                if (!mp[make_pair(x, y)]) {
                    g[x].push_back(y);
                    du[y]++;
                    mp[make_pair(x, y)] = 1;
                }
            }
        }
    }
    for (int i = 1; i <= colorsum; i++) {
        if (du[i] == 0) {
            que.push(i);
            ans[i] = 1;
        }
    }
    while (que.size()) {
        int x = que.front();
        que.pop();
        nowmaxn[x] += cnt[x];
        for (int i = 0; i < g[x].size(); i++) {
            v = g[x][i];
            if (nowmaxn[x] > nowmaxn[v]) {
                ans[v] = ans[x];
                nowmaxn[v] = nowmaxn[x];
            } else if (nowmaxn[x] == nowmaxn[v]) {
                ans[v] = (ans[v] + ans[x]) % X;
            }
            du[v]--;
            if (du[v] == 0) {
                que.push(v);
            }
        }
    }
    int anser = 0;
    int maxnn = 0;
    for (int i = 1; i <= colorsum; i++) {
        if (nowmaxn[i] > maxnn) {
            anser = ans[i];
            maxnn = nowmaxn[i];
        } else if (nowmaxn[i] == maxnn) {
            anser = (anser + ans[i]) % X;
        }
    }
    cout << maxnn << endl;
    cout << anser << endl;

}
View Code

 

posted @ 2019-07-16 16:00  Aragaki  阅读(158)  评论(0编辑  收藏  举报