【PAT甲级】1076 Forwards on Weibo (30分)

解题过程的小记录,如有错误欢迎指出。

难度:四星(弄清样例后题目就不难,因为自己赋值=写成==折腾半天,憨憨行为)

题目分析

给出每位博主和ta的粉丝列表,假设博主发一条微博ta的粉丝就会转发,而ta的粉丝的粉丝看到也会转发,求一位博主的粉丝最多能被转发多少次

注意点

  1. 因为本题是每个博主都需要独自查找,所以inq队列要在BFS函数体内初始化
  2. 博主是第0层,超过给定的层数的转发不计数
  3. 给出的列表是每个人fo的博主,而不是ta的粉丝列表,这里不要搞反

我的解题过程

思路

  1. 输入数据,我用的是领接表,要注意给出的列表是下标用户fo的博主,也就是ta会转发的人,我设置成(博主->下标用户)的领接表,表明转发的方向
  2. 写BFS函数,利用队列,此处注意队列插入的是node,多增加了一个变量layer,这个node只在BFS函数体内用到,因为对于每一个查询来说,每个结点的layer都是不同的,所以在函数体外只要保存图的结构即可
  3. 写BFSTrace函数,返回值是转发次数
  4. 进行输出

bug

  1. 输入格式少些了个%d(我到底在干嘛
  2. 赋值写成了==,导致反复进入队列(我到底在干嘛again

代码

#include<iostream>
#include<vector>
#include<queue>

using namespace std;

const int MAXV = 1005;
int n, l, cnt = 0;

struct node {
	int v;
	int layer;
};

vector<int> G[MAXV];

void BFS(int index) {
	bool inq[MAXV] = { false };//因为每次都是独立查询,所以要在函数体内初始化
	queue<node> q;
	node start;
	start.v = index;
	start.layer = 0;
	q.push(start);
	inq[index] = true;
	while (!q.empty()) {
		node now = q.front();
		q.pop();
		if (now.layer > l) break;
		if (now.layer > 0) {
			cnt++;
		}
		int u = now.v;
		for (int i = 0; i < G[u].size(); i++) {
			int v = G[u][i];
			if (inq[v] == false) {
				node next;
				next.v = v;
				next.layer = now.layer + 1;
				q.push(next);
				inq[next.v] = true;//这里原来的赋值写成==,所以无法正确赋值导致错误
			}
		}
	}
}

int BFSTrace(int index) {
	cnt = 0;
	BFS(index);
	return cnt;
}

int main()
{
	scanf("%d %d", &n, &l);//刚开始这里都写错了,%d只写了一遍
	for (int i = 1; i <= n; i++) {
		int v = i, k, u;
		scanf("%d", &k);
		for (int j = 0; j < k; j++) {
			scanf("%d", &u);
			G[u].push_back(v);
		}
	}
	int querylist;
	scanf("%d", &querylist);
	for (int i = 0; i < querylist; i++) {
		int index;
		scanf("%d", &index);
		printf("%d\n", BFSTrace(index));
	}
    return 0;
}

dalao的代码

全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~

借鉴点

  1. 在找孩子的时候判断是否<=L,并且如果没有进过队列就cnt++,这样就自动避免了本身的情况,以及不会把超过层数的加入队列
  2. memst(inq, false, sizeof(inq));可以用作每次inq的恢复初始化(在头文件string.h中)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值