zoukankan      html  css  js  c++  java
  • [bzoj1093][ZJOI2007]最大半连通子图

    n<=100000,m<=1000000

    缩点之后,就成为了一个扩扑图,题目转化为求最长链的长度以及数量,然后随意dp呗

    #include<cstdio>
    #include<iostream>
    #define ll long long
    using namespace std;
    inline int read()
    {
        int  x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    bool inq[200005];
    int n,m,cnt=0,head[200005],dn=0,cc,dfn[100005],low[100005],q[200005],top=0,bel[200005],mark[200005],mod,in[200005];
    ll f[200005],s[200005],mx[200005],ans=0,sum=0;
    struct edge{
        int to,next;
    }e[2000005];
    void ins(int f,int t){e[++cnt].next=head[f];head[f]=cnt;e[cnt].to=t;}
    
    void tarjan(int x)
    {
        dfn[x]=low[x]=++dn;inq[x]=1;q[++top]=x;
        for(int i=head[x];i;i=e[i].next)
            if(!dfn[e[i].to]){tarjan(e[i].to);low[x]=min(low[x],low[e[i].to]);}
            else if(inq[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);
        if(low[x]==dfn[x])
        for(++cc;q[top+1]!=x;inq[q[top]]=0,++s[cc],bel[q[top--]]=cc);
    }
    
    void dp()
    {
        int top=0,tail=0;
        for(int i=n+1;i<=cc;i++)if(!in[i])q[++top]=i,f[i]=1,mx[i]=s[i];
        while(top!=tail)
        {
            int now=q[++tail];
            for(int i=head[now];i;i=e[i].next)
            {
                in[e[i].to]--;if(!in[e[i].to])q[++top]=e[i].to;
                if(mark[e[i].to]==now)continue;
                if(mx[now]+s[e[i].to]>mx[e[i].to])
                {mx[e[i].to]=mx[now]+s[e[i].to];f[e[i].to]=f[now];}
                else if(mx[now]+s[e[i].to]==mx[e[i].to])f[e[i].to]+=f[now];
                if(f[e[i].to]>=mod)f[e[i].to]-=mod;mark[e[i].to]=now;
            }
        }
        
    }
    
    int main()
    {    
        cc=n=read();m=read();mod=read();
        for(int i=1;i<=m;i++){int u=read(),v=read();ins(u,v);}
        for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=n;i++)for(int j=head[i];j;j=e[j].next)
        if(bel[i]!=bel[e[j].to])ins(bel[i],bel[e[j].to]),in[bel[e[j].to]]++;
        dp();
        for(int i=n+1;i<=cc;i++)
        {
            if(mx[i]>sum)sum=mx[i],ans=f[i];
            else if(mx[i]==sum)ans=(ans+f[i])%mod;
        }
        cout<<sum<<endl<<ans;
        return 0;
    }
  • 相关阅读:
    基于项目中遇到的技术问题,谈谈SharedPreferences的使用的注意问题
    mongodb数据库从库同步主库维护js脚本
    MongoDB数据库日志备份压缩脚本
    mongodb数据库磁盘碎片整理。
    mongodb表字段处理生成域名字段
    根据当前进程号,获取进程下线程数目
    mongodb mapreduce示例
    MongoDB数据库库级锁研究分析
    mongodb库表信息监控脚本
    利用JAVA设计一个可视化日历
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1093.html
Copyright © 2011-2022 走看看