【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\n%d\n",maxnode,ans);
    return 0;
}
View Code
posted @ 2017-03-22 17:56  redwind  阅读(...)  评论(...编辑  收藏