PAT 1076. Forwards on Weibo (BFS + 剪枝)

一开始想floyd, 但n^3 = 10^9, 要10秒了可能;

土一点的dijkstra超时, 因为dijkstra中寻找当前未访问过的距离最小值时,是对所有点进行遍历;以及对每个这样的点,是遍历map[1010][1010]数组。这样导致每遍dijkstra就是O(2*n*n)的复杂度。如果m >= n, 仍可能出现n^3的情况;

然后及用priority_queue来维护当前未访问过的距离最小值,用邻接表来维护每个点的相邻结点。

事实上,这就退化成BFS了.... 所以BFS+剪枝就能搞定的。(代码从135行变成了75行)


注意到,这里的边是有向边 —— "n l"后的第 i 行输入:

代表用户 i 关注了 m 个用户, 进而是该m个的用户的微博可以被用户 i 转发,从而有向边应该从那些 m 个用户指向 i.


代码。耗时2s. 有人耗时200+ms就完成了,知道怎么做的教我一下呗。

#include <iostream>
#include <queue>
#include <list>
#include <cstring>

using namespace std;

struct Node
{
	int m_id;
	int m_level;
	Node() {}
	Node(int id, int level): m_id(id), m_level(level) {}
};

int n, l, k, id;
bool in_queue[1010];
list<int> edge[1010];
queue<Node> q;

int bfs(Node now)
{
//	cout << "bfs" << endl;
	int cnt = -1;
	while (q.empty() == false)
	{
		q.pop();
	}
	q.push(now);
	in_queue[now.m_id] = true;
	while (q.empty() == false)
	{
		Node node = q.front();
//		in_queue[node.m_id] = true;
		q.pop();
		if (node.m_level > l)
		{
			break;
		}
//		cout << node.m_id << endl;
		++ cnt;
		for (auto it = edge[node.m_id].begin(); it != edge[node.m_id].end(); ++ it)
		{
			if (in_queue[*it] == false)
			{
				q.push( Node(*it, node.m_level+1) );
				in_queue[*it] = true;
			}
		}
	}
	return cnt;
}

int main()
{
	scanf("%d%d", &n, &l);
	for (int i = 1; i <= n; ++ i)
	{
		scanf("%d", &k);
		for (int j = 0; j < k; ++ j)
		{
			scanf("%d", &id);
			edge[id].push_back(i);
		}
	}
	scanf("%d", &k);
	for (int i = 0; i < k; ++ i)
	{
		memset(in_queue, 0, sizeof(in_queue));
		scanf("%d", &id);
		printf("%d\n", bfs(Node(id, 0)));
	}

	return 0;
}


耗时220ms.. 不懂怎么做到的

你可能感兴趣的:(C++,dijkstra,pat,bfs,剪枝)