【Luogu P2002&P2341】消息扩散/受欢迎的奶牛

Luogu P2002
Luogu P2341
使用强连通分量算法缩点
第一题统计入度为0的个数强连通分量数。
第二题的答案为当且仅当仅有一个强连通分量的出度为0时该强连通分量的节点数,原因如下:若一个强连通分量出度为0,则说明这个强连通分量的喜爱无法对外传递;若有多个强连通分量出度为0,则说明这几个强连通分量的喜爱无法对外传递,则不可能产生明星。
有关强连通分量的知识,可以看我的另一篇博客
【Luogu P3387】缩点模板(强连通分量Tarjan&拓扑排序)

AC代码

P2002:

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e5+10,maxm=5*1e5+10;
struct data
{
    int to,next;
}e[maxm];
int low[maxn],dfn[maxn],stk[maxn],head[maxn],tim,cnt,tot,in[maxn];
bool vis[maxn];
int val[maxn],scc[maxn],n,m,a,b;
void tarjan(int u)
{
    low[u]=dfn[u]=++tim;
    stk[++cnt]=u;
    vis[u]=true;
    for (int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if (!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else 
        {
            if (vis[v]) low[u]=min(low[u],dfn[v]);
        }
    }
    if (low[u]==dfn[u])
    {
        tot++;
        while (true)
        { 
            val[tot]++;
            scc[stk[cnt]]=tot;
            vis[stk[cnt]]=false;
            cnt--;
            if (stk[cnt+1]==u) break;
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        e[i].to=b;
        e[i].next=head[a];
        head[a]=i;
    }
    for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
    for (int i=1;i<=n;i++)
        for (int j=head[i];j;j=e[j].next)
        {
            int u=i,v=e[j].to;
            if (scc[u]!=scc[v])
                in[scc[v]]++;
        }
    int flag=0;
    for (int i=1;i<=tot;i++) if (!in[i]) flag++;
    printf("%d",flag);
    return 0;
}

P2341:

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e4+10,maxm=5*1e4+10;
struct data
{
    int to,next;
}e[maxm];
int low[maxn],dfn[maxn],stk[maxn],head[maxn],tim,cnt,tot,out[maxn];
bool vis[maxn];
int val[maxn],scc[maxn],n,m,a,b;
void tarjan(int u)
{
    low[u]=dfn[u]=++tim;
    stk[++cnt]=u;
    vis[u]=true;
    for (int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if (!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else 
        {
            if (vis[v]) low[u]=min(low[u],dfn[v]);
        }
    }
    if (low[u]==dfn[u])
    {
        tot++;
        while (true)
        { 
            val[tot]++;
            scc[stk[cnt]]=tot;
            vis[stk[cnt]]=false;
            cnt--;
            if (stk[cnt+1]==u) break;
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        e[i].to=b;
        e[i].next=head[a];
        head[a]=i;
    }
    for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
    for (int i=1;i<=n;i++)
        for (int j=head[i];j;j=e[j].next)
        {
            int u=i,v=e[j].to;
            if (scc[u]!=scc[v])
                out[scc[u]]++;
        }
    int flag=0;
    for (int i=1;i<=tot;i++) if (!out[i]) cnt=i,flag++;
    if (flag==1) printf("%d\n",val[cnt]);
    else printf("0");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/notscience/p/11823644.html