一开始想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.. 不懂怎么做到的