P2835 刻录光盘

原题链接

题解

好抽象啊!!!

大概思路就是把强连通分量看作一个点,然后在此基础上找入度为零的点

code

#include<bits/stdc++.h>
using namespace std;
vector<int> G[205];
int in[205]={0};//代表强连通分量的入度
int belong[205]={0};//代表每个点属于哪个强连通分量
int len=0,cnt=0;//len代表时间戳,cnt代表强连通分量的个数
int vis[205]={0};//代表时间戳
int low[205]={0};//代表这个强连通分量内的点能到达的最小时间戳
stack<int> q;//栈的作用是,将同一强连通分量的点进行归类

int along[205]={0};
void ss(int now)
{
    vis[now]=++len;
    low[now]=vis[now];

    q.push(now);
    along[now]=1;//数组along的作用是判断点是否是同一轮遍历的,不然时间戳小的点做了非同一强连通分量的子节点使父节点low值错误更新
    for(auto next:G[now])
    {
        if(!vis[next])
        {
            ss(next);
            low[now]=min(low[now],low[next]);
        }
        else if(along[next])
        {
            low[now]=min(low[now],vis[next]);
        }
    }

    if(low[now]==vis[now])
    {
        ++cnt;
        int x;
        do
        {
            x=q.top();
            q.pop();
            along[x]=0;
            belong[x]=cnt;
        }while(x!=now);
    }
}
int main()
{
    int n,x;
    cin>>n;

    for(int i=1;i<=n;i++)
        while(cin>>x&&x!=0) G[i].push_back(x);

    for(int i=1;i<=n;i++)
        if(!vis[i]) ss(i);

    for(int i=1;i<=n;i++)
        for(auto next:G[i])
            if(belong[i]!=belong[next])  in[belong[next]]++;

    int ans=0;
    for(int i=1;i<=cnt;i++) ans+=(!in[i]);

    cout<<ans<<endl;
    return 0;
}

posted @   纯粹的  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示