BZOJ 1093: [ZJOI2007]最大半连通子图 Tarjan+DP

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/89706559

title

BZOJ 1093
LUOGU 2272
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 ≤100000, 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

analysis

首先观察到这个图中如果有某个部分是强连通的,那其实可以把这整个部分都看做一个点,这样并不会对结果产生影响。

所以首先对这个图进行 t a r j a n tarjan 缩点,并记录下每个连通块的大小,和每个点所在的连通块。

缩点之后,会发现这个图变成了一个 D A G DAG (有向无环图),我们要对这个 D A G DAG 求出最长链的大小和个数。

因为这个图是无环的,所以我们可以按照拓扑序进行 D P DP f [ i ] f[i] 表示到第 i i 个连通块的最长链大小, g [ i ] g[i] 表示个数。

很容易就想到了转移的方法:

  • 1. g [ i ] = g [ i ] + g [ j ] ( i f f [ j ] + s i z [ i ] = = f [ i ] ) g[i]=g[i]+g[j](if:f[j]+siz[i]==f[i])

  • 2. g [ i ] = g [ j ] , f [ i ] = f [ j ] + s i z [ i ] ( i f f [ j ] + s i z [ i ] > f [ i ] ) g[i]=g[j],f[i]=f[j]+siz[i](if:f[j]+siz[i]>f[i])

按照这个转移状态就可以啦。

刚开始对这个状态转移不太理解,一直觉得应该是 i i 转移到 j j 才对,然而试了半天都是不对的,
那位神犇路过,请解答一下,感激不尽啊。。

但是要注意缩点之后会出现大量重边拓扑排序之前要去重,所以用 v e c o t r vecotr 存储缩点后的图还是挺好的,排序去重比较方便。

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;

template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

int ver[maxm<<1],Next[maxm<<1],head[maxn],len;
inline void add(int x,int y)
{
    ver[++len]=y,Next[len]=head[x],head[x]=len;
}

int dfn[maxn],low[maxn],id;
int Stack[maxn],top;
int belong[maxn],siz[maxn],tot;
bool instack[maxn];
inline void tarjan(int x)
{
    dfn[x]=low[x]=++id;
    Stack[++top]=x;
    instack[x]=1;
    for (int i=head[x]; i; i=Next[i])
    {
        int y=ver[i];
        if (!dfn[y])
        {
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if (instack[y])
            low[x]=min(low[x],dfn[y]);
    }
    if (low[x]==dfn[x])
    {
        int k;
        ++tot;
        do
        {
            k=Stack[top--];
            belong[k]=tot;
            instack[k]=0;
            ++siz[tot];
        } while (k!=x);
    }
}

vector<int>E[maxm];
int length[maxn],deg[maxn];
int ans[maxn],cnt;
inline void Topsort()
{
    queue<int>q;
    for (int i=1; i<=tot; ++i)
        if (!deg[i]) q.push(i),E[0].push_back(i),++length[0];
    while (!q.empty())
    {
        int x=q.front();
        q.pop();
        ans[++cnt]=x;
        for (int i=0; i<length[x]; ++i)
            if (!--deg[E[x][i]]) q.push(E[x][i]);
    }
}

int f[maxn],g[maxn];
int main()
{
    int n,m,mod;
    read(n);read(m);read(mod);
    for (int i=1; i<=m; ++i)
    {
        int a,b;
        read(a);read(b);
        add(a,b);
    }
    //缩点
    for (int i=1; i<=n; ++i)
        if (!dfn[i]) tarjan(i);
    for (int x=1; x<=n; ++x)
        for (int i=head[x]; i; i=Next[i])
        {
            int y=ver[i];
            if (belong[x]==belong[y]) continue;
            E[belong[x]].push_back(belong[y]);
        }

    for (int i=1; i<=tot; ++i) sort(E[i].begin(),E[i].end());
    for (int i=1; i<=tot; ++i) length[i]=unique(E[i].begin(),E[i].end())-E[i].begin();
    for (int i=1; i<=tot; ++i)
        for (int j=0; j<length[i]; ++j)
            ++deg[E[i][j]];
    Topsort();

    for (int i=tot; ~i; --i)
    {
        int x=ans[i];
        f[x]=siz[x],g[x]=1;
        for (int j=0; j<length[x]; ++j)
        {
            int y=E[x][j];
            if (f[x]<f[y]+siz[x])
                f[x]=f[y]+siz[x],g[x]=g[y];
            else if (f[x]==f[y]+siz[x])
                (g[x]+=g[y])%=mod;
        }
    }
    printf("%d\n%d\n",f[0],g[0]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/89706559