题目来源:华为机试题
好难的题目!自己想不出来,参考了别人的代码:http://blog.csdn.net/xvwentao89/article/details/38560503
思路是让有最多未收到消息的朋友的节点作为下一次转发的节点,这个思路有bug,就像上面的blog下面的评论说的。
代码仅供参考。
朋友圈转发信息
描述:
在一个社交应用中,两个用户设定朋友关系后,则可以互相收到对方发布或转发的信息。当一个用户发布或转发一条信息时,他的所有朋友都能收到该信息。
现给定一组用户,及用户之间的朋友关系。
问:当某用户发布一条信息之后,为了让每个人都能在最早时间收到这条信息,这条信息最少需要被转发几次?
假设:对所有用户而言:
1)朋友发出信息到自己收到该信息的时延为T(T>0);
2)如需转发,从收到信息到转发出信息的时延为0。
用例保证:在给定的朋友圈关系中,任何人发布的信息总是能通过N(N>=0)次转发让其他所有用户收到。
例如:
下图表示某个朋友圈关系(节点间连线表示朋友关系)中,用户1在时刻0发布信息之后,两种不同的转发策略。
黄色节点表示转发用户,蓝色数字为用户收到信息的时间。
运行时间限制: 无限制
内存限制: 无限制
输入:
Sender
[消息创建者编号]
Relationship
[朋友关系列表,1,2 表示1和2是朋友关系]
End
如下:
Sender
1
Relationship
1,2
1,3
1,4
2,5
2,6
3,6
4,6
4,7
5,6
5,8
5,9
6,7
6,8
6,9
7,9
10,7
End
输出:
当某用户发布一条信息之后,为了让每个人都能在最早时间收到这条信息,这条信息最少需要被转发的次数
样例输入:
Sender
1
Relationship
1,2
1,3
1,4
2,5
2,6
3,6
4,6
4,7
5,6
5,8
5,9
6,7
6,8
6,9
7,9
10,7
End
样例输出:
4
我的答案(java):
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Map<Integer,Node> allNodes = new HashMap<>(); // 保存所有用户
Scanner sc = new Scanner(System.in);
sc.nextLine(); // 接收 "Sender"
int senderId = Integer.valueOf(sc.nextLine());
sc.nextLine(); // 接收 "Relationship"
// 创建用户关系
String str;
while (!(str = sc.nextLine()).equals("End")) {
String id1, id2;
id1 = str.split(",")[0];
id2 = str.split(",")[1];
// 先从集合中取,集合中没有再 new
Node node = allNodes.get(Integer.valueOf(id1));
if(node == null){
node = new Node(Integer.valueOf(id1));
}
Node frd = allNodes.get(Integer.valueOf(id2));
if(frd == null){
frd = new Node(Integer.valueOf(id2));
}
// 互相添加好友
node.getFriends().add(frd);
frd.getFriends().add(node);
// 添加到集合
allNodes.put(node.getId(),node);
allNodes.put(frd.getId(),frd);
}
sc.close();
// printAllNodes(allNodes);
Node root = allNodes.get(senderId);
root.setReceived(true);// 发送者先收到消息
root.sendMsg();// 发送者向所有朋友发送消息
List<Node> senders = new ArrayList<>();
Node sender = root;
int transCount = 0; // 统计转发次数
while (!isAllNodeReceived(allNodes)) {
while (sender.findNext() != null) {
Node transmitter = sender.findNext();
transmitter.sendMsg();
senders.add(transmitter);
transCount++;
System.out.println("transmitter "+transmitter.getId());
}
if (senders.size() > 0) {
sender = senders.remove(0);
}
}
System.out.println(transCount);
}
/**
* 判断所有节点中是否还有节点未收到消息
*
* @param allNodes
* @return
*/
public static boolean isAllNodeReceived(Map<Integer,Node> allNodes) {
boolean b = true;
Set<Integer> keys = allNodes.keySet();
for(Integer key : keys){
Node node = allNodes.get(key);
if (!node.isReceived()) {
b = false;
}
}
return b;
}
/**
* 打印所有节点
* @param allNodes
*/
public static void printAllNodes(Map<Integer,Node> allNodes) {
Set<Integer> keys = allNodes.keySet();
for(Integer key : keys){
Node node = allNodes.get(key);
System.out.println(node.getId());
}
}
}
class Node {
private int id; // 节点编号
private boolean received = false; // 节点是否收到过消息
private List<Node> friends = new ArrayList<>(); // 朋友列表
public Node() {
}
public Node(int id) {
super();
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isReceived() {
return received;
}
public void setReceived(boolean received) {
this.received = received;
}
public List<Node> getFriends() {
return friends;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
Node node = (Node) obj;
if (id != node.id) {
return false;
}
if(received != node.received){
return false;
}
if(friends.equals(node.friends)){
return true;
}
return false;
}
@Override
public int hashCode() {
return id;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Node " + this.id);
sb.append(" isReceived " + isReceived());
sb.append(" has Friends: ");
for (Node node : friends) {
sb.append(node.id + " ");
}
return sb.toString();
}
/*
* 返回某个节点的朋友数
*/
public int numberOfFriends() {
return getFriends().size();
}
/*
* 向所有的朋友节点发消息
*/
public void sendMsg() {
Iterator<Node> it = getFriends().iterator();
while (it.hasNext()) {
Node friend = it.next();
friend.setReceived(true);
}
}
/**
* 返回当前节点没有收到消息的朋友的数目
*
* @return
*/
public int getUnReceivedFriendsNum() {
int num = 0;
for (Node frid : friends) {
if (frid.received == false)
num++;
}
return num;
}
/**
* 返回当前节点没有收到消息的朋友列表
*
* @return
*/
public List<Node> getUnReceivedFriendsList() {
List<Node> list = new ArrayList<>();
for (Node frid : friends) {
if (frid.received == false)
list.add(frid);
}
return list;
}
/**
* 从当前节点的朋友中找到下一次转发的节点
*
* @return
*/
public Node findNext() {
int max = 0; // 看谁未收到消息的朋友最多
Node transmitter = null;
// 如果某个节点,存在未接收到消息的朋友,则将它加入转发列表
for (Node frid : friends) {
if (transmitter == null) {
transmitter = frid;
}
int num = frid.getUnReceivedFriendsNum();
if (max < num) {
max = num;
transmitter = frid;
}
}
if (max == 0) {
transmitter = null;
}
return transmitter;
}
}