BZOJ 1093 最大半连通子图

Posted on 2016-11-06 18:17  ziliuziliu  阅读(215)  评论(0编辑  收藏  举报

缩点求最长链。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#define maxv 100500
#define maxe 1000500
using namespace std;
struct edge
{
    int u,v,nxt;
}e[maxe];
struct pnt
{
    int id,rank;
}p[maxv];
int n,m,mod,x,y,g[maxv],nume=1,tot=0,bel[maxv],times=0,dfn[maxv],low[maxv],stack[maxv],top=0;
set <int> s[maxv];
set <int> ::iterator it;
int dp1[maxv],dp2[maxv],size[maxv],d[maxv],ans1=0,ans2=0;
bool ins[maxv];
queue <int> q;
bool cmp(pnt x,pnt y) {return x.rank<y.rank;}
void addedge(int u,int v)
{
    e[++nume].u=u;e[nume].v=v;
    e[nume].nxt=g[u];g[u]=nume;
}
void tarjan(int x)
{
    dfn[x]=low[x]=++times;stack[++top]=x;ins[x]=true;
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (!dfn[v])
        {
            tarjan(v);
            low[x]=min(low[x],low[v]);
        }
        else if (ins[v]) low[x]=min(low[x],dfn[v]);
    }
    if (dfn[x]==low[x])
    {
        tot++;int now;
        do
        {
            now=stack[top];size[tot]++;
            bel[now]=tot;ins[now]=false;
            top--;        
        }while (now!=x);
    }
}
void topusort()
{
    for (int i=1;i<=tot;i++)
    {
        p[i].id=i;
        if (!d[i]) {q.push(i);p[i].rank=1;}
    }
    while (!q.empty())
    {
        int head=q.front();q.pop();
        for (it=s[head].begin();it!=s[head].end();it++)
        {
            int v=*it;
            if (!--d[v])
            {
                p[v].rank=p[head].rank+1;
                q.push(v);
            }
        }
    }
    sort(p+1,p+tot+1,cmp);
}
void dp()
{
    for (int i=tot;i>=1;i--)
    {
        int flag=0;
        int x=p[i].id;
        for (it=s[x].begin();it!=s[x].end();it++)
        {
            flag=1;int v=*it;
            if (dp1[v]>dp1[x]) {dp1[x]=dp1[v];dp2[x]=dp2[v];}
            else if (dp1[v]==dp1[x]) dp2[x]=(dp2[x]+dp2[v])%mod;
        }
        if (!flag) dp2[x]=1;dp1[x]+=size[x];
        if (ans1<dp1[x]) {ans1=dp1[x];ans2=dp2[x];}
        else if (ans1==dp1[x]) ans2=(ans2+dp2[x])%mod;
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&mod);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        addedge(x,y);
    }
    for (int i=1;i<=n;i++)
        if (!dfn[i]) tarjan(i);
    for (int i=2;i<=nume;i++)
    {
        int x=e[i].u,y=e[i].v;
        if ((s[bel[x]].find(bel[y])==s[bel[x]].end()) && (bel[x]!=bel[y]))
        {
            s[bel[x]].insert(bel[y]);
            d[bel[y]]++;
        }
    }
    topusort();
    dp();
    printf("%d\n%d\n",ans1,ans2);
    return 0;
}