• bzoj 1093 [ZJOI2007]最大半连通子图——缩点+拓扑


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1093

    缩点+拓扑,更新长度的时候维护方案数。

    结果没想到处理缩点后的重边,这样的话方案数会算多。

    学习人家处理重边的方法好好。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5,M=1e6+5;
    int n,m,hd[N],rd[N],cd[N],mod,dp[N],f[N],ans,prn,lst[N];
    int dfn[N],low[N],tim,cnt,col[N],sta[N],top,h,t,siz[N];
    bool ins[N];
    struct Ed{
        int nxt,fr,to;
        Ed(int n=0,int f=0,int t=0):nxt(n),fr(f),to(t) {}
    }ed[M];
    int rdn()
    {
        int ret=0;char ch=getchar();
        while(ch>'9'||ch<'0')ch=getchar();
        while(ch>='0'&&ch<='9')(ret*=10)+=ch-'0',ch=getchar();
        return ret;
    }
    void tarjan(int cr)
    {
        dfn[cr]=low[cr]=++tim;
        ins[cr]=1;sta[++top]=cr;
        for(int i=hd[cr],v;i;i=ed[i].nxt)
            if(!dfn[v=ed[i].to])
                tarjan(v),low[cr]=min(low[cr],low[v]);
            else if(ins[v])low[cr]=min(low[cr],dfn[v]);
        if(dfn[cr]==low[cr])
        {
            cnt++;
            while(sta[top]!=cr)
            {
                int k=sta[top--];col[k]=cnt;ins[k]=0;siz[cnt]++;
            }
            top--;col[cr]=cnt;ins[cr]=0;siz[cnt]++;
        }
    }
    int main()
    {
        n=rdn();m=rdn();mod=rdn();
        int x,y;
        for(int i=1;i<=m;i++)
        {
            x=rdn();y=rdn();
            ed[i]=Ed(hd[x],x,y);hd[x]=i;
        }
        for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
        memset(hd,0,sizeof hd);
        for(int i=1,u,v;i<=m;i++)
            if((u=col[ed[i].fr])!=(v=col[ed[i].to]))
                ed[i]=Ed(hd[u],u,v),hd[u]=i,rd[v]++,cd[u]++;
        h=1;t=0;
        for(int i=1;i<=n;i++)
            if(!rd[i])dp[i]=siz[i],f[i]=1,sta[++t]=i;
        while(h<=t)
        {
            int k=sta[h++];
            for(int i=hd[k],v;i;i=ed[i].nxt)
            {
                rd[v=ed[i].to]--;if(!rd[v])sta[++t]=v;
                if(lst[v]==k)continue;//会把k的出边全走完,所以不会对v先x再y再x地更新 
                if(dp[k]+siz[v]>dp[v])dp[v]=dp[k]+siz[v],f[v]=f[k];
                else if(dp[k]+siz[v]==dp[v])(f[v]+=f[k])%=mod;
                lst[v]=k;
            }
        }
        for(int i=1;i<=n;i++)if(!cd[i])
            if(dp[i]>ans)ans=dp[i],prn=f[i];
            else if(dp[i]==ans)(prn+=f[i])%=mod;
        printf("%d
    %d
    ",ans,prn);
        return 0;
    }
  • 相关阅读:
    linux中fork()函数详解(原创!!实例讲解) (转载)
    超级课程表原理解析(如何获取网页内容)
    MySql中时间类型总结
    android Json详解
    Jsoup解析Html中文文档
    Mysql相关
    Chrome驱动安装问题
    Airtest 网易 UI 自动化工具 Airtest 浅用记录
    关于Airtest的使用探索
    Sublime text 3搭建Python开发环境及常用插件安装
  • 原文地址:https://www.cnblogs.com/Narh/p/9376248.html
Copyright © 2020-2023  润新知