zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    OpenStack 对接 Ceph
    《Netty权威指南》(二)NIO 入门
    《Netty权威指南》(一)走进 Java NIO
    进程间通信 IPC(Inter-Process Communication)
    CentOS7 下安装 iSCSI Target(tgt) ,使用 Ceph rbd
    CentOS7 下编译安装 Samba,什么是 SMB/CIFS 协议
    《Netty权威指南》目录
    CentOS7 下安装 NFS,Linux/Windows 作为客户端
    数据结构汇总
    Ceph 块设备
  • 原文地址:https://www.cnblogs.com/Narh/p/9376248.html
Copyright © 2011-2022 走看看