88分求条

P2272 [ZJOI2007] 最大半连通子图

BarkFlorr @ 2024-11-09 12:44:17

rt

code:

#include<bits/stdc++.h>
using namespace std;
int n,m,mod,ti,color,k,c,maxn=1,maxm=0;
int dfn[100005];//访问时间
int low[100005],lower[100005];//从这里开始能访问到的最早节点(dfn最小)
int co[100005];//连通分量
int rd[100005];//入度
int dp[100005],ff[100005];
bool fl[100005],flag[100005];
vector<int>p[100005];
vector<int>q[100005];
stack<int>st;
map<pair<int,int>,bool>mp;
queue<int>tp;
void dfs(int u){
    if(flag[u]) return ;
    fl[u]=1;
    flag[u]=1;
    dfn[u]=++ti;
    low[u]=dfn[u];
    st.push(u);
    for(int i=0;i<p[u].size();i++){
        int v=p[u][i];
        if(!flag[v]){
            dfs(v);
            low[u]=min(low[u],low[v]);
        }
        else if(fl[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        co[u]=++color;
        dp[color]=1;
        ff[color]=1;
        while(st.top()!=u) co[st.top()]=color,fl[st.top()]=false,st.pop(),dp[color]++;
        st.pop();
        fl[u]=0;
        // cout<<"ltk:"<<u<<" "<<color<<"\n";
    }
}
void topu(){
    for(int i=1;i<=color;i++) if(rd[i]==0) tp.push(i);
    while(!tp.empty()){
        int u=tp.front();
        tp.pop();
        for(int i=0;i<q[u].size();i++){
            int v=q[u][i];
            rd[v]--;
            if(rd[v]==0) tp.push(v);
            if(dp[u]+1<dp[v]) continue;
            if(dp[u]+1>dp[v]){
                dp[v]=dp[u]+1;
                ff[v]=0;
            }
            if(dp[u]+1==dp[v]) ff[v]++;
            maxn=max(maxn,dp[v]);
        }
    }
}
int main(){
    cin>>n>>m>>mod;
    for(int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        p[x].push_back(y);
    }
    for(int i=1;i<=n;i++) dfs(i);
    for(int i=1;i<=n;i++){
        int u=co[i];
        for(int j=0;j<p[i].size();j++){
            int v=co[p[i][j]];
            if(mp[make_pair(u,v)]||u==v) continue;
            // cout<<u<<"->"<<v<<"\n";
            mp[make_pair(u,v)]=1;
            q[u].push_back(v);
            rd[v]++;
        }
    }
    topu();
    for(int i=1;i<=color;i++){
        // cout<<dp[i]<<" "<<ff[i]<<"\n";
        if(dp[i]==maxn) maxm+=ff[i];
    }
    cout<<maxn<<"\n"<<maxm%mod;
    return 0;
}

|