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

    ime Limit: 30 Sec  Memory Limit: 162 MB
    Submit: 3625  Solved: 1436
    [Submit][Status][Discuss]

    Description

      一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意
    两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,
    则称G'是G的一个导出子图。若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图。若G'是G所有半连通子图
    中包含节点数最多的,则称G'是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K
    ,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。

    Input

      第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整
    数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。N ≤1
    00000, M ≤1000000;对于100%的数据, X ≤10^8

    Output

      应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.

    Sample Input

    6 6 20070603
    1 2
    2 1
    1 3
    2 4
    5 6
    6 4

    Sample Output

    3
    3

    HINT

     

    Source

    Tarjan缩点

    然后求最长链和方案数

    屠龙宝刀点击就送

    #include <cstdio>
    #include <cctype>
    #define N 1000500
    #define rep(a,b,c) for(int x,y,a=b;a<=c;++a)
    #define Rep(a,b) for(int a=head[b];a;a=nextt[a])
    #define REP(a,b) for(int a=_head[b];a;a=_nextt[a])
    
    template<typename T>
    inline void read(T &x)
    {
        register char ch=getchar();
        for(x=0;!isdigit(ch);ch=getchar());
        for(;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    }
    bool instack[N],vis[N];
    int n,m,Mod,cnt,top,tim,sumcol,sum[N],val[N],f[N],head[N],nextt[N],to[N],stack[N],low[N],dfn[N],col[N];
    int _head[N],_nextt[N],_to[N],_cnt;
    template<typename S> inline int min(S a,S b) {return a>b?b:a;}
    void tarjan(int x)
    {
        low[x]=dfn[x]=++tim;
        instack[x]=true;
        stack[++top]=x;
        Rep(i,x)
        {
            int v=to[i];
            if(!dfn[v]) {tarjan(v);low[x]=min(low[x],low[v]);}
            else if(instack[v]) low[x]=min(low[x],dfn[v]); 
        }
        if(low[x]==dfn[x])
        {
            sumcol++;
            int k;
            do
            {
                k=stack[top--];
                instack[k]=false;
                col[k]=sumcol;
            }while(k!=x);
        }
    }
    template<typename Y> inline int max(Y a,Y b) {return a>b?a:b;}
    void Dfs(int x)
    {
        if(vis[x]) return;
        vis[x]=1;
        f[x]=val[x];
        REP(i,x)
        {
            int v=_to[i];
            Dfs(v);
            f[x]=max(f[x],f[v]+val[x]);
        }
        REP(i,x)
        {
            int v=_to[i];
            if(f[x]==f[v]+val[x]) sum[x]=(sum[x]+sum[v])%Mod;
        }
        if(!sum[x]) sum[x]=1;
    }
    int main(int argc,char *argv[])
    {
        read(n);read(m);read(Mod);
        rep(i,1,m)
        {
            read(x);read(y);
            nextt[++cnt]=head[x];to[cnt]=y;head[x]=cnt;
        }
        rep(i,1,n) if(!dfn[i]) tarjan(i);
        rep(i,1,n)
        {
            val[col[i]]++;
            Rep(j,i)
            {
                int v=to[j];
                if(col[i]!=col[v])
                {
                    REP(k,col[i]) if(_to[k]==col[v]) goto flag;
                    _nextt[++_cnt]=_head[col[i]];_to[_cnt]=col[v];_head[col[i]]=_cnt;
                }
                flag:;
            }
        }
        int ans=0,ret=0;
        rep(i,1,sumcol) if(!vis[i]) Dfs(i);
        rep(i,1,sumcol) ans=max(ans,f[i]);
        rep(i,1,sumcol) if(f[i]==ans) ret=(ret+sum[i])%Mod;
        printf("%d
    %d",ans,ret);
        return 0;
    }
  • 相关阅读:
    【Educational Codeforces Round 101 (Rated for Div. 2) C】Building a Fence
    【Codeforces Round #698 (Div. 2) C】Nezzar and Symmetric Array
    【Codeforces Round #696 (Div. 2) D】Cleaning
    【Codeforces Round #696 (Div. 2) C】Array Destruction
    【Educational Codeforces Round 102 D】Program
    【Educational Codeforces Round 102 C】No More Inversions
    【Good Bye 2020 G】Song of the Sirens
    【Good Bye 2020 F】Euclid's nightmare
    使用mobx入门
    requestAnimationFrame 控制速度模拟setinterval
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7644206.html
Copyright © 2011-2022 走看看