洛谷P1726 上白澤慧音 tarjan

題目鏈接:https://www.luogu.com.cn/problem/P1726

tarjan的一道模板題,t=1連一條單向邊,t=2連一條雙向邊。tarjan跑一遍,一個絕對連通區域就是一個強連通分量。tarjan中每次找到一個強連通分量,記錄這個強連通分量有多少個點。然後找到強連通分量最大的那個,從前往後找,就保證了字典序最小的優先,最後輸出屬於那個連通塊的點即可。
代碼如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=5e3+5;
const int maxm=1e5+5;
int head[maxn];
struct node
{
    int to,next;
}edge[maxm];
int cnt;
void add(int x,int y)
{
    edge[++cnt].next=head[x];
    edge[cnt].to=y;
    head[x]=cnt;
}
int dfn_number,top,color;
int dfn[maxn],low[maxn],col[maxn],stc[maxn],col_num[maxn];
bool vis[maxn];
void tarjan(int u)
{
    dfn[u]=low[u]=++dfn_number;
    stc[++top]=u;
    vis[u]=1;
    for(int i=head[u];i;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]);
    }
    if(dfn[u]==low[u])
    {
        int len=1;
        vis[u]=false;
        col[u]=++color;
        while(stc[top]!=u)
        {
            vis[stc[top]]=false;
            col[stc[top--]]=color;
            len++;
        }
        top--;
        col_num[color]=len;
    }
}
int n,m;
int opt,x,y;
int main()
{
    scanf("%d %d",&n,&m);
    while(m--)
    {
        scanf("%d %d %d",&x,&y,&opt);
        if(opt==1)
        {
            add(x,y);
        }
        else
        {
            add(x,y);
            add(y,x);
        }
    }
    for(int i=1;i<=n;i++)
    if(!dfn[i])
    tarjan(i);
    int ma=0,t;
    for(int i=1;i<=n;i++)
    {
        if(col_num[col[i]]>ma)
        {
            ma=col_num[col[i]];
            t=col[i];
        }
        //cout<<col[i]<<endl;
    }
    printf("%d\n",ma);
    for(int i=1;i<=n;i++)
    {
        if(col[i]==t)
        printf("%d ",i);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章