• P2272 [ZJOI2007]最大半连通子图


    P2272 [ZJOI2007]最大半连通子图

    Tarjan缩点+拓扑排序

    attention:注意判断新图中的重边

    先用Tarjan缩点,处理出每个分量的大小。

    然后建个新图,设叶子节点的方案数为1,蓝后跑一遍拓扑排序即可。

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #include<cctype>
    using namespace std;
    template <typename T> inline T min(T &a,T &b) {return a<b ?a:b;}
    template <typename T> inline T max(T &a,T &b) {return a>b ?a:b;}
    template <typename T> inline void read(T &x){
        char c=getchar(); x=0; bool f=1;
        while(!isdigit(c)) f= !f||c=='-' ? 0:1,c=getchar();
        while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
        x= f ? x:-x;
    }
    template <typename T> inline void output(T x){
        if(!x) {putchar(48); return ;}
        if(x<0) putchar('-'),x=-x;
        int wt[50],l=0;
        while(x) wt[++l]=x%10,x/=10;
        while(l) putchar(wt[l--]+48);
    }
    struct data{
        int f,t;
        bool operator < (const data &tmp) const{return f<tmp.f||(f==tmp.f&&t<tmp.t);}
        bool operator != (const data &tmp) const{return f!=tmp.f||t!=tmp.t;}
    }a[1000002];
    int n,m,mod,d[100002],ted; long long f[100002],ans;
    int dfs_clock,dfn[100002],low[100002],_top,st[100002],tot,be[100002],val[100002];
    int cnt1,hd1[100002],nxt1[1000002],ed1[100002],poi1[1000002];
    int cnt2,hd2[100002],nxt2[1000002],ed2[100002],poi2[1000002],_in[100002];
    int rts,rt[100002],mxd;
    queue <int> h;
    inline void add1(int x,int y){
        nxt1[ed1[x]]=++cnt1; hd1[x]= hd1[x] ? hd1[x]:cnt1;
        ed1[x]=cnt1; poi1[cnt1]=y;
    }
    inline void add2(int x,int y){
        nxt2[ed2[x]]=++cnt2; hd2[x]= hd2[x] ? hd2[x]:cnt2;
        ed2[x]=cnt2; poi2[cnt2]=y; ++_in[y];
    }
    inline void tarjan(int x){
        dfn[x]=low[x]=++dfs_clock; st[++_top]=x;
        for(int i=hd1[x];i;i=nxt1[i]){
            if(!dfn[poi1[i]]) tarjan(poi1[i]),low[x]=min(low[x],low[poi1[i]]);
            else if(!be[poi1[i]]) low[x]=min(low[x],dfn[poi1[i]]);
        }
        if(low[x]==dfn[x]){
            be[x]=++tot; ++val[tot];
            while(st[_top]!=x) be[st[_top--]]=tot,++val[tot];
            --_top;
        }
    }
    void find(){ //拓扑排序
        for(int i=1;i<=tot;++i)
            if(!_in[i])
                h.push(i),d[i]=val[i],f[i]=1;
        while(!h.empty()){
            int x=h.front(); h.pop();
            if(!hd2[x]) {rt[++rts]=x; mxd=max(mxd,d[x]); continue;}
            for(int i=hd2[x];i;i=nxt2[i]){
                if(d[poi2[i]]<d[x]+val[poi2[i]]){ //如果深度更大就重新结算
                    d[poi2[i]]=d[x]+val[poi2[i]];
                    f[poi2[i]]=f[x]%mod;
                }else if(d[poi2[i]]==d[x]+val[poi2[i]]){
                    f[poi2[i]]=(f[poi2[i]]+f[x])%mod;
                }
                if((--_in[poi2[i]])==0) h.push(poi2[i]);
            }
        }
    }
    int main(){
        read(n); read(m); read(mod); int q1,q2;
        for(int i=1;i<=m;++i) read(q1),read(q2),add1(q1,q2);
        for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
        for(int i=1;i<=n;++i)
            for(int j=hd1[i];j;j=nxt1[j])
                if(be[i]!=be[poi1[j]])
                    a[++ted]=(data){be[i],be[poi1[j]]};
        sort(a+1,a+ted+1);
        for(int i=1;i<=ted;++i) //把重边判掉
            if(a[i]!=a[i-1])
                add2(a[i].f,a[i].t);
        find();
        for(int i=1;i<=rts;++i) if(d[rt[i]]==mxd) ans=(ans+f[rt[i]])%mod; //深度最大的累加起来
        output(mxd); putchar('
    '); output(ans);
        return 0; 
    }
  • 相关阅读:
    免装版tomcat注册成windows系统服务方法
    IE下判断IE版本的语句...[if lte IE 8]……[endif]
    HTTP 消息结构
    RESTful API 设计指南
    Spring Cloud Alibaba Sentinel 流量卫兵
    SpringBoot 整合 ES 实现 CRUD 操作
    SpringBoot项目创建与第一个SSM项目示例
    SpringBoot整合邮件发送
    SpringBoot日志处理之Logback
    Java实现AES加密解密
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9708916.html
Copyright © 2020-2023  润新知