bfs求重复路径(v.size是unsign int)(本题最大坑点,可能有套娃)

GYM 102501K

vj传送门

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题意:

给你一个t,问有多少个与t相邻的点,那条边真真实实存在。(本题有向图)

思路:

  1. 反向建图,之后把问题转换成,从与t相邻的点出发。
  2. 把每个与t相邻的点,构建祖先为其本身。
  3. 跑bfs,
  4. 如果一个点有多次访问,那么可能就对这个点有多条路,而因为是以每个与t相邻的点为起点,所以当祖先和待访问的节点相同时,就说明由自己走向自己,不操作,
  5. 当不是祖先时,就访问,并标记。
  6. 最后统计与t相邻的点(只访问过一次。)
  7. 一个点可能访问多次,有可能要套娃现象。

反思

  1. 本题让我对bfs有了更深层次的理解(水题刷少了,bfs只会dij,没什么用,对队友没贡献)
  2. 本题考察了套娃,小心!!!!
  3. 一个fa记录源头,很巧妙
  4. 本次对于vector真是大失败,不会瞎用,训练的时候做不出来就算了,之后补提时RE。
  5. 下面开始对vector进行实验:
    在这里插入图片描述

可以发现:
5. 当v里没元素时,即动态数组为空,v.size()输出是0.
6. 可当我放一个元素进去时,再输出v.size()-2就奇异了,并不是-1而是一个很大的数,而当赋值给一个int len 时,再输出就不会了。
7. 后面我用printf进行实验,谜底就解开了,其实v.size是unsign int型,而cout不用占位符,所以输出时就应该是unsigne int 输出

vector使用误区(楼主的sb做法qwq)

许多初学者(包括我)在使用时都直接把它当作数组使用,其实是不一样的.vector是动态数组,使用前需要分配空间,跳过这一步直接调用成员函数,可能会有莫名RE

vector正确的做法

  1. 用其内部的构造函数给他分配空间,or push_back().
  2. 分配后的动态数组就和正常数组差不多了。

AC

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#include <vector>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define mst(x,a) memset(x,a,sizeof(x))
#define fzhead EDGE(int _to, int _v, int _next)
#define fzbody to(_to),v(_v),next(_next)
using namespace std;
typedef long long ll;
typedef pair<int,int>pa;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
int n,m,t,cnt;
struct EDGE
{
    int to,next,v;
    EDGE(){}
    fzhead:fzbody{}
}e[maxn];
int vis[maxn],head[maxn];
vector<int>b;
void add(int bg, int ed, int val)
{
    e[++cnt]=EDGE(ed,val,head[bg]);
    head[bg]=cnt;
 }
void spfa(int s)
{
      queue<pa>q;
    for(int i=head[s]; i!=-1; i=e[i].next)
    {
        q.push(mp(e[i].to,e[i].to));
    }
     while(!q.empty())
    {
        int u=q.front().fi,fa=q.front().se;
        q.pop();
        if(vis[u]>=3)continue;
        if(!vis[u])vis[u]=1;
        else
        {
            if(u!=fa)vis[u]++;
            else continue;
        }
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            int va=e[i].to;
            if(va==s)continue;
            q.push(mp(va,fa));
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&t);
    mst(head,-1);
    For(i,1,m)
    {
        int x,y;
        scanf("%d%d", &x,&y);
      add(y,x,1);
    }
    spfa(t);
    for(int i=head[t];i!=-1; i=e[i].next)
    {
        int u=e[i].to;
        if(vis[u]==1)
        {
            b.push_back(u);
        }
    }
    cout<<b.size()<<endl;
    sort(b.begin(),b.end());
   int b.size();
    For(i,0,len-1)cout<<b[i]<<endl;
   return 0;
}

ac(博主的代码太丑了,前排给大佬)

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
#define mp make_pair
#define fi first
#define se second
//#define pb push_back
#define mst(x,a) memset(x,a,sizeof(x))
#define fzhead EDGE(int _to, int _v, int _next)
#define fzbody to(_to),v(_v),next(_next)
using namespace std;
typedef long long ll;
typedef pair<int,int>pa;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
int n,m,t,cnt;
struct EDGE
{
    int to,next,v;
    EDGE(){}
    fzhead:fzbody{}
}e[maxn];
int dis[maxn],vis[maxn],head[maxn];
int in[maxn];
void add(int bg, int ed, int v)
{
    e[++cnt]=EDGE(ed,v,head[bg]);
    head[bg]=cnt;
    in[bg]++;
    //cout<<endl;
 //   cout<<bg<<' '<<in[bg]<<endl;
    //cout<<endl;
}
void dij(int s)
{
    For(i,0,n-1){vis[i]=0;dis[i]=INF;in[i]=0;}
    //priority_queue<pa>q;
    queue<pa>q;
    //dis[s]=0;//q.push(mp(0,s));
    for(int i=head[s]; i!=-1; i=e[i].next)
    {
        int v=e[i].to;
        in[v]++;
        q.push(mp(v,v));
    }
    while(!q.empty())
    {
        int u=q.front().fi,fa=q.front().se;
        q.pop();
        if(vis[u]>=3)continue;
        if(!vis[u])vis[u]=1;
        else
        {
            vis[u]++;
        }
       // cout<<dis[u]<<' '<<u<<endl;
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].to,w=e[i].v;
            if(v==s)
            {
                continue;
            }
            else if(in[v]&&fa!=v)
            {
                in[v]=0;
                continue;
            }
           // cout<<v<<' '<<in[v]<<endl<<endl;
            q.push(mp(v,fa));
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&t);
    mst(head,-1);
    For(i,1,m)
    {
        int x,y;
        scanf("%d%d", &x,&y);
      //  add(y,x,1);
      add(y,x,1);
    }
    dij(t);
    int ans=0;
    For(i,0,n-1)
    {
        if(in[i]==1&&i!=t)ans++;
      //  cout<<in[i]<<' ';
    }
  //  For(i,0,n-1)
  //  {
       // if(in[i]==1&&i!=t)
       // {
           // int v=head[i];
          //  cout<<"v="<<v<<' '<<"i="<<i<<endl;
          //  cout<<i<<' ';
           // if(e[v].to==t)
        //    {
             //   ans++;
            //    vis[i]=1;
           // }
       // }
        //cout<<dis[i]<<' ';
   // }
  //  cout<<endl;
    cout<<ans<<endl;
    For(i,0,n-1)if(in[i]==1&&i!=t)cout<<i<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值