zoukankan      html  css  js  c++  java
  • 【BZOJ1093】最大半联通子图

    1093: [ZJOI2007]最大半连通子图

    Time Limit: 30 Sec  Memory Limit: 162 MB
    Submit: 3111  Solved: 1228
    [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

    Sol

    涨姿势了 最长路还能这么搞……

    首先tarjan缩点成DAG,然后每个点拓扑排序(其实就是求最长路,边权为scc[v]) 然后dp统计答案 没了

    /*To The End Of The Galaxy*/
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<iomanip>
    #include<bitset>
    #include<stack>
    #include<map>
    #include<set>
    #include<cmath>
    #include<complex>
    #define debug(x) cerr<<#x<<"="<<x<<endl
    #define INF 0x7f7f7f7f
    #define llINF 0x7fffffffffffll
    #define P(x,y) (((x-1)*c)+y)
    using namespace std;
    typedef pair<int,int> pii;
    typedef long long ll;
    inline int init()
    {
        int now=0,ju=1;char c;bool flag=false;
        while(1)
        {
            c=getchar();
            if(c=='-')ju=-1;
            else if(c>='0'&&c<='9')
            {
                now=now*10+c-'0';
                flag=true;
            }
            else if(flag)return now*ju;
        }
    }
    inline long long llinit()
    {
        long long now=0,ju=1;char c;bool flag=false;
        while(1)
        {
            c=getchar();
            if(c=='-')ju=-1;
            else if(c>='0'&&c<='9')
            {
                now=now*10+c-'0';
                flag=true;
            }
            else if(flag)return now*ju;
        }
    }
    struct edge
    {
        int from,to,val,pre;
    }Edge[2000005],e[2000005];
    int dfn[100005],low[100005],dfs_time,cnt,n,m;
    bool instack[100005];
    stack<int> st;
    map<pii,int> mp;
    int in[100005],mod,dis[100005],f[100005];
    int scc[100005],head[100005],bel[100005],topt,sccnumber;
    inline void addedge(int from,int to,int val)
    {
        ++cnt;
        Edge[cnt]=((edge){from,to,val,head[from]});
        head[from]=cnt;
    }
    inline void tarjan(int now)
    {
        dfn[now]=low[now]=++dfs_time;
        st.push(now);instack[now]=1;
        for(int j=head[now];j;j=Edge[j].pre)
        {
            if(!dfn[Edge[j].to])
            {
                tarjan(Edge[j].to);
                low[now]=min(low[now],low[Edge[j].to]);
            }
            else if(instack[Edge[j].to])
            {
                low[now]=min(low[now],dfn[Edge[j].to]);
            }
        }
        if(dfn[now]==low[now])
        {
            ++sccnumber;
            while(1)
            {
                topt=st.top();st.pop();
                bel[topt]=sccnumber;
                scc[sccnumber]++;
                instack[topt]=false;
                if(dfn[topt]==low[topt])break;
            }
        }
    }
    queue<int> q;
    int maxnode,ans;
    inline void rebuild()
    {
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i])
            {
                tarjan(i);
            }
        }
        for(int i=1;i<=cnt;i++)
        {
            e[i]=Edge[i];
        }
        memset(head,0,sizeof(head));
        for(int i=1;i<=cnt;i++)
        {
            if(bel[e[i].from]!=bel[e[i].to]&&!mp[make_pair(bel[e[i].from],bel[e[i].to])])
            {
                in[bel[e[i].to]]++;
                mp[make_pair(bel[e[i].from],bel[e[i].to])]=1;
                addedge(bel[e[i].from],bel[e[i].to],1);
            }
        }
        for(int i=1;i<=sccnumber;i++)
        {
            if(in[i]==0)
            {
                q.push(i);
                dis[i]=scc[i];
                f[i]=1;
            }
            else
            {
                dis[i]=0;
            }
        }
    }
    inline void toposort()
    {
        int now;
        while(!q.empty())
        {
            now=q.front();q.pop();
            for(int j=head[now];j;j=Edge[j].pre)
            {
                in[Edge[j].to]--;
                if(in[Edge[j].to]==0)q.push(Edge[j].to);
                if(dis[now]+scc[Edge[j].to]>dis[Edge[j].to])
                {
                    dis[Edge[j].to]=dis[now]+scc[Edge[j].to];
                    f[Edge[j].to]=f[now];
                }
                else if(dis[now]+scc[Edge[j].to]==dis[Edge[j].to])
                {
                    f[Edge[j].to]=(f[Edge[j].to]+f[now])%mod;
                }
            }
        }
    }
    int main()
    {
        int a,b;
        n=init();m=init();mod=init();
        for(int i=1;i<=m;i++)
        {
            a=init();b=init();
            addedge(a,b,1);
        }
        rebuild();
        toposort();
        for(int i=1;i<=n;i++)
        {
            if(maxnode<dis[i])
            {
                maxnode=dis[i];
                ans=f[i];
            }
            else if(maxnode==dis[i])
            {
                ans=(ans+f[i])%mod;
            }
        }
        printf("%d
    %d
    ",maxnode,ans);
        return 0;
    }
    View Code
  • 相关阅读:
    C++学习:explicit关键字
    CMake入门——简单CMakeLists的编写
    EOJ Monthly 2020.1 E. 数的变幻
    CF #610Div2 B2.K for the Price of One (Hard Version) (dp解法 && 贪心解法)
    hdu 5147 Sequence II【树状数组/线段树】
    hdu 6581 Vacation【思维】
    dubbo源码学习(一)之ExtensionLoader
    xsd学习教程
    spring自定义schema学习
    如何更好地学习dubbo源代码(转)
  • 原文地址:https://www.cnblogs.com/redwind/p/6601212.html
Copyright © 2011-2022 走看看