1076 Forwards on Weibo (30 分)

题意

在微博中,每个用户都可能被若千个其他用户关注。而当该用户发布一条信息时,他的关注者就可以看到这条信息并选择是否转发它,且转发的信息也可以被转发者的关注者再次转发,但同一用户最多只转发该信息一次(信息的最初发布者不会转发该信息)。现在给出N个用户的关注情况( 即他们各自关注了哪些用户)以及一个转发层数上限L,并给出最初发布消息的用户编号,求在转发层数上限内消息最多会被多少?

思路

  1. 首先考虑如何建图。由于题目给定的数据是用户关注的情况(而不是被关注的情况),因此如果用户X关注了用户Y,则需要建立由Y指向X的有向边,来表示Y发布的消息可以传递到X并被X转发。
  2. 在建图完毕后,使用DFS或者BFS都可以得到需要的结果。如果使用DFS来遍历,只要控制遍历深度不超过题目给定的层数L即可,遍历过程中计数访问到的结点个数(细节处理会比较麻烦)。如果使用BFS来遍历,则需要把结点编号和层号建立成结构体,然后控制遍历层数不超过L。

注意点

  1. 由于可能形成环,必须控制每个用户只能转发消息1次(即遍历时只能访问1次)。
  2. 使用DFS遍历很容易出错,因为需要注意一种情况,即可能有一个用户X在第i次被访问,但是此时已经达到转发层数上限,故无法继续遍历。但若该用户可以通过另一条路径更快地被访问到,那么是可以继续深入遍历的。除此之外,DFS还可能导致同一个结点的转发次数被重复计算(需要额外设置一个数组来记录结点是否已经转发过信息,才能最终解决此问题)。本题不推荐使用DFS来写。
  3. 如果DFS写得不够好,就会超时,因此本题更推荐使用BFS,且BFS不会出现②中的问题,写法更直接。
const int N=1010;
vector<int> g[N];
int dep[N];
bool vis[N];
int n,m,L;

void bfs(int st)
{
    queue<int> q;
    q.push(st);
    vis[st]=true;
    dep[st]=0;

    int cnt=0;
    while(q.size())
    {
        int t=q.front();
        q.pop();

        ans++;

        for(int i=0;i<g[t].size();i++)
        {
            int j=g[t][i];
            dep[j]=dept[t]+1;
            if(!vis[j] && dep[j] <= L)
            {
                vis[j]=true;
                q.push(j);
            }
        }
    }
}

int main()
{
    cin>>n>>L;

    for(int i=1;i<=n;i++)
    {
        int k;
        cin>>k;
        for(int j=0;j<k;j++)
        {
            int x;
            cin>>x;
            g[x].pb(i);
        }
    }

    cin>>m;
    while(m--)
    {
        memset(vis,0,sizeof vis);
        ans=0;

        int x;
        cin>>x;
        dfs(x,0);
        cout<<endl;
        cout<<ans<<endl;

    }
    //system("pause");
    return 0;
}
posted @ 2021-02-28 21:18  Dazzling!  阅读(113)  评论(0编辑  收藏  举报