P3916 图的遍历——题解

来一发bfs版本

对于这个图来讲我们可以反向建图

将到达的最大点转化为是否可以被当前的最大点到达

所以我们从n到1枚举起点

然后可以发现这样的性质

如果一个点被标记过,也就是说这个点有答案

和该点相连的所有点都被标记过,因此无需搜索这个点。

在遇到有答案的点是跳过即可

上代码~我知道你们就是想要这个!

#include<stdio.h>
#include<queue>
using namespace std;
struct data
{
    int v;int next;
}edge[100010];
int alist[100010];
int cnt;
void add(int u,int v)
{
    edge[++cnt].v=v;
    edge[cnt].next=alist[u];
    alist[u]=cnt;
    return;
}
int n;int m;
int res[100010];//答案数组
queue <int> q;
int now;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int u;int v;
        scanf("%d%d",&u,&v);
        add(v,u);//反向建图
    }
    for(int i=n;i>=1;i--)
    {
        if(res[i]!=0)continue;//如果这个点被搜过所有相连点均被搜过可以跳过
        q.push(i);
        while(!q.empty())//对点ibfs
        {
            now=q.front();q.pop();
            res[now]=i;
            int next=alist[now];
            while(next)
            {
                int v=edge[next].v;
                if(res[v]==0)
                {
                    q.push(v);
                }
                next=edge[next].next;
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        printf("%d ",res[i]);//输出答案
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值