求助 tarjan

P2272 [ZJOI2007] 最大半连通子图

phmaprostrate @ 2021-10-30 18:47:17

一个点 Re 一个点 Wa.

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 10;
const int M = 2e6 + 10;
int n,m,p,total;
struct node {
    int to,next;
    bool operator < (const node aa)const {
        return to < aa.to;
    }
} tr[2 * M];
struct node2{
    int from,to;
}ne[N];
set<node> pp;
int h[N],k = 0;
int dfn[N],low[N],num = 0;
int s[N],ins[N],top = 0,cnt = 0;
int siz[N],id[N];
int from[N],to[N];
int dp[N],e[N];
int d[N],in[N],cnt2 = 0,idd;
queue<int> q;
bool cmp(node2 aa,node2 bb){
    if(aa.from != bb.from) return aa.from < bb.from;
    else return aa.to < bb.to;
}
void add(int from,int to) {
    tr[++k].to = to;
    tr[k].next = h[from];
    h[from] = k;
}
void tarjan(int x) {
    dfn[x] = low[x] = ++num;
    s[++top] = x,ins[x] = true;
    for(int i = h[x] ; i ; i = tr[i].next) {
        int y = tr[i].to;
        if(!dfn[y]) {
            tarjan(y);
            low[x] = min(low[x],low[y]);
        } else if(ins[y]) low[x] = min(low[x],dfn[y]);
    }
    if(low[x] == dfn[x]) {
        int z;
        cnt ++;
        do {
            z = s[top--];
            id[z] = cnt;
            siz[cnt] ++;
            ins[z] = false;
        } while(z != x);
    }
}
void init() {
    memset(tr,0,sizeof(tr));
    k = 0;
    memset(h,0,sizeof(h));
}
void check(int u,int v) {
    if(dp[v] < dp[u] + siz[v]) {
        dp[v] = dp[u] + siz[v];
        e[v] = 0;
        if(dp[idd] < dp[v]) idd = v;
    }
    if(dp[v] == dp[u] + siz[v])
        e[v] = (e[v] + e[u]) % p;
}
void rever(){
    sort(ne + 1,ne + 1 + k,cmp);
    for(int i = 1 ; i <= k ; i ++){
        if(ne[i].from == ne[i - 1].from && ne[i].to == ne[i - 1].to) continue;
        add(ne[i].from,ne[i].to);
        in[ne[i].to] ++;
    }
}
void tuopu() {
    for(int i = 1 ; i <= cnt ; i ++) if(!in[i]) q.push(i),dp[i] = siz[i],e[i] = 1;
    for(int i = 1 ; i <= cnt ; i ++) if(dp[idd] < dp[i]) idd = i;
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        d[++cnt2] = u;
        for(int i = h[u] ; i ; i = tr[i].next) {
            int y = tr[i].to;
            in[y] --;
            check(u,y);
            if(!in[y]) q.push(y);
        }
    }
}
signed main() {
    cin >> n >> m >> p;
    for(int i = 1 ; i <= m ; i ++) {
        cin >> from[i] >> to[i];
        add(from[i],to[i]);
    }
    for(int i = 1 ; i <= n ; i ++)
        if(!dfn[i]) tarjan(i);
    init();
    for(int i = 1 ; i <= m ; i ++) {
        int a = id[from[i]],b = id[to[i]];
        if(a != b) {
         ne[++k].from = a;
         ne[k].to = b;
        }
    }
    rever();
    tuopu();

    for(int i = 1 ; i <= cnt ; i ++) {
        if(dp[i] == dp[idd])
            total = (total + e[i]) % p;
        //if(dp[i] > dp[idd]) idd = i,total = e[i];
    //  else if(dp[i] == dp[idd]) total += e[i],total %= p;
    }
    cout << dp[idd] <<endl << total;
    return 0;
}

by phmaprostrate @ 2021-10-30 18:58:42

此帖已结,我是sb. 为啥 N 开大 20 倍就过了。


|