bzoj1093: [ZJOI2007] Maximum semi-connected subgraph scc shrink point + dp on dag

A directed graph G=(V, E) is called semi-connected (Semi-Connected), if it satisfies: ?u, v∈V, and u→v or v→u, that is, for any
two points u in the graph, v, there is a directed path from u to v or a directed path from v to u. If G'=(V', E') satisfies V'?V, and E' is all edges in E related to V',
then G' is said to be a derived subgraph of G. If G' is a derived subgraph of G, and G' is semi-connected, then G' is said to be a semi-connected subgraph of G.
If G' is the largest number of nodes in all semi-connected subgraphs of G, then G' is said to be the largest semi-connected subgraph of G. Given a directed graph G, request the number of nodes K of the largest semi-connected subgraph of G
, and the number of different largest semi-connected subgraphs C. Since C may be relatively large, only the remainder of C to X is required to be output.

Solution: shorten the scc point, the same connected component must be mutually reachable, and then it becomes a dag. You only need to run a dag on the dp to find the longest path, and then you need to record the number of the longest path solutions, you need to pay attention After the point is determined, the edge is determined, so when scc shrinks the point, it is necessary to judge the heavy edge

/**************************************************************
    Problem: 1093
    User: walfy
    Language: C++
    Result: Accepted
    Time:4788 ms
    Memory:49420 kb
****************************************************************/
 
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)
 
using namespace std;
 
const double g=10.0,eps=1e-11;
const int N=100000+10,maxn=1000000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
 
int n,m,X;
stack<int>s;
vector<int>v[N],vv[N],ans[N];
int dfn[N],low[N];
int ins[N],inans[N];
int num,ind;
int a[maxn],b[maxn];
void tarjan(int u)
{
    ins[u]=2;
    low[u]=dfn[u]=++ind;
    s.push(u);
    for(int i=0;i<v[u].size();i++)
    {
        int t=v[u][i];
        if(dfn[t]==0)
        {
            Tarjan (s);
            low[u]=min(low[u],low[t]);
        }
        else if(ins[t]==2)low[u]=min(low[u],dfn[t]);
    }
    if(low[u]==dfn[u])
    {
        ++num;
        while(!s.empty()){
            int k=s.top();
            s.pop();
            ins[k]=1;
            ans[num].push_back(k);
            inans[k]=num;
            if(k==u)break;
        }
    }
}
map<pii,int>ma;
void scc()
{
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            Tarjan (i);
    for(int i=0;i<m;i++)
    {
        int x=inans[a[i]],y=inans[b[i]];
        if(x!=y&&!ma[mp(x,y)])vv[x].pb(y),ma[mp(x,y)]=1;
    }
}
pii dp[N];
pii DP(int u)
{
    if(dp[u].fi!=-1)return dp[u];
    dp[u].fi=ans[u].size(),dp[u].se=1;
    for(int i=0;i<vv[u].size();i++)
    {
        int x=vv[u][i];pii te=DP(x);
        if(dp[u].fi<te.fi+ans[u].size())
        {
            dp[u]=te,dp[u].fi=te.fi+ans[u].size();
//            printf("%d %d %d %d\n",u,x,dp[u].fi,dp[u].se);
        }
        else if(dp[u].fi==te.fi+ans[u].size())
        {
            dp[u].se=(dp[u].se+te.se)%X;
//            printf("%d %d %d +++%d\n",u,x,dp[u].se,te.se);
        }
    }
    return dp[u];
}
intmain ()
{
    scanf("%d%d%d",&n,&m,&X);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&a[i],&b[i]);
        v[a[i]].pb(b[i]);
    }
    scc();
    memset(dp,-1,sizeof dp);
    for(int i=1;i<=n;i++)
        DP(i);
    int ma=0;
    for(int i=1;i<=num;i++)ma=max(ma,dp[i].fi);//,printf("%d %d\n",dp[i].fi,dp[i].se);
    int ans=0;
    for(int i=1;i<=num;i++)if(dp[i].fi==ma)ans=(ans+dp[i].se)%X;
    printf("%d\n%d\n",ma,ans);
    return 0;
}
/***********************
 
***********************/
View Code

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325500024&siteId=291194637