1. 程式人生 > >【洛谷2661】信息傳遞 強聯通分量

【洛谷2661】信息傳遞 強聯通分量

clas str ems ctype sin add mat edge math

分析

tarjan算出全部的聯通塊,在求出聯通塊裏最小的個數。

AC代碼

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cctype>
#include <cmath>
#include <time.h>
 
using namespace std;
 
#define ms(a,b) memset(a,b,sizeof(a))
 
const int maxn=200010;
 
struct Edge{
    int to,next;
}edge[maxn<<1];
 
int nedge,sum,dep,top,n,m,cnt;
int head[maxn],dfn[maxn],stack[maxn],low[maxn],od[maxn],vis[maxn],id[maxn];
int belong[maxn],block[maxn];
 
inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
 
void add_edge(int a,int b)
{
    edge[nedge]=(Edge){b,head[a]}; head[a]=nedge++;
}
 
void tarjan(int u)
{
    dfn[u]=low[u]=++dep;
    stack[top++]=u;
    vis[u]=1;
    for (int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[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]);
        }
    }
    int j;
    if (dfn[u]==low[u])
    {
        sum++;
        do{
            j=stack[--top];
            belong[j]=sum;
            vis[j]=0;
        }
        while (u!=j);
    }
}
 
int main()
{
    nedge=0;
    ms(head,-1);
    n=read();
    for (int i=1;i<=n;i++)
    {
        int a=read();
        add_edge(i,a);
    }
    for (int i=1;i<=n;i++)
    {
        if (!dfn[i]) tarjan(i);
    }
    for (int i=1;i<=n;i++)
    {
        block[belong[i]]++;
    }
    int ans=maxn;
    for (int i=1;i<=sum;i++)
    {
        if (block[i]!=1) ans=min(block[i],ans);
    }
    printf("%d\n",ans);
    return 0;
}

【洛谷2661】信息傳遞 強聯通分量