标签:als 传递 lag 代码 算法 next scanf sci bool
Luogu P2002
Luogu P2341
使用强连通分量算法缩点
第一题统计入度为0的个数强连通分量数。
第二题的答案为当且仅当仅有一个强连通分量的出度为0时该强连通分量的节点数,原因如下:若一个强连通分量出度为0,则说明这个强连通分量的喜爱无法对外传递;若有多个强连通分量出度为0,则说明这几个强连通分量的喜爱无法对外传递,则不可能产生明星。
有关强连通分量的知识,可以看我的另一篇博客
【Luogu P3387】缩点模板(强连通分量Tarjan&拓扑排序)
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;
}
【Luogu P2002&P2341】消息扩散/受欢迎的奶牛
标签:als 传递 lag 代码 算法 next scanf sci bool
原文地址:https://www.cnblogs.com/notscience/p/11823644.html