@Override publicintsendIndirectMessage(int id)throws MessageIdNotFoundException { if (!containsMessage (id) || containsMessage (id) && getMessage (id).getType () == 1) { thrownew MessageNotFoundExc (id); } int id1 = getMessage (id).getPerson1 ().getId (); int id2 = getMessage (id).getPerson2 ().getId (); try { if (!isCircle (id1, id2)) { return -1; } } catch (PersonIdNotFoundException ignored) { } Person p1 = getPerson (id1); Person p2 = getPerson (id2); p1.addSocialValue (getMessage (id).getSocialValue ()); p2.addSocialValue (getMessage (id).getSocialValue ()); Message m = getMessage (id); if (m instanceof RedEnvelopeMessage) { p1.addMoney (-((RedEnvImpl) m).getMoney ()); p2.addMoney (((RedEnvImpl) m).getMoney ()); } elseif (m instanceof EmojiMessage) { emojiHeatList.computeIfPresent (((EmojiMessage) m).getEmojiId (), (k, v) -> v + 1); } ((LinkedList<Message>) p2.getMessages ()).addFirst (m); messages.remove (m.getId ()); HashMap<Integer, Integer> distance = new HashMap<>(); HashSet<Person> solved = new HashSet<>(); PriorityQueue<Person> unsolved = new PriorityQueue<>(Comparator.comparingInt (o -> distance.get (o.getId ()))); for (Person p : people.values ()) { if (p.equals (p1)) { distance.put (p.getId (), p.queryValue (p1)); solved.add (p); } else { distance.put (p.getId (), p.isLinked (p1) ? p.queryValue (p1) : Integer.MAX_VALUE); unsolved.add (p); } } while (!unsolved.isEmpty ()) { //find the closest vertex around S in (V - S) Person closestPerson = unsolved.poll (); solved.add (closestPerson); //refresh the vertices around closestPerson in (V - S) for (Person pp : ((PersonImpl) closestPerson).getAcquaintance ().values ()) { if (distance.get (pp.getId ()) > distance.get (closestPerson.getId ()) + closestPerson.queryValue (pp) && unsolved.contains (pp) && !solved.contains (pp)) { unsolved.remove (pp); distance.put (pp.getId (), distance.get (closestPerson.getId ()) + closestPerson.queryValue (pp)); unsolved.add (pp); } } } return distance.get (id2); }
初始状态为:V = {StartPoint}, S = VertexSet - {StartPoint}, 然后不断在 S 中寻找 ** 距离点集 V 最近的点 P**,将其从 V 中去掉并加入 S,更新所有 S 中点的距离后进入下一个循环直到 S = {}。这里有一个可以优化性能的点,那就是在更新 S 中其他点的距离时不需要便利所有点,只需要在 P 的邻居之间寻找即可,而在本次作业中每个人都记录了自己认识的人的集合,所以直接遍历这个集合并更新距离即可。最后的实验也证明了这样的效率是很高的。
##🎈本地测试数据
在自己的本地测试中主要是随机生成的数据点,因为程序预先设计了许多异常,并有异常对应的特殊输出,所以数据点可以随机进行生成。主要是根据 Random rand; int p = rand.nextInt (); 给出的 p 值设置一些区间来生成数据。当然根据一些特定指令可以手写一些小规模的针对性测试点。