没去机试,题目在这位仁兄的博客里有http://blog.csdn.net/xvwentao89/article/details/38560503
渣渣还没想到简单的模型,只有一个复杂些的思路:
(1)因为要保证每个人都在最短的时间内收到消息,所以到达每个人的消息传递路径必须是最短路径,由此我们可以将朋友圈的消息传递按距离分成几层,渣渣下面的代码用的spfa算最短路,然后再将最短路长度相同的人分到同一组,写完之后想想其实直接一次BFS就可以将两者完成了,复杂度还低些……
(2)分层之后,只要保证每一层的所有人都会被上一层通知到即可,由此可以逐层求出两层之间需要转发的最小次数,渣渣目前用的暴搜,要是能用DP就好了,唉……
由于题目中没有告知输入规模、标号范围神马的,只是保证了图的连通性,所以我也就没有假设所有人按1~N标号,只假设所有人都被唯一的正整数标识
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
/*
suppose every person has been labeled by a unique positive number
*/
int sponsor; //the news sender
map<int, set<int> > friends;//relationship graph, use set to avoid repeated edges
map<int, int> dis; //each person's shortest distance to sponsor
queue<int> q; //used in spfa
map<int, bool> inq; //used in spfa
vector<vector<int> > level; //group people with same distance to sponsor
int fromLevel, forwards; //used in DFS to find minimum forwards needed between fromLevel to fromLevel + 1
map<int,int> toldBy; //used in DFS to mind each person's teller in previous level
void input()
{
string line;
int x, y;
//input sender
getline(cin, line);
cin >> sponsor;
getline(cin, line);
//input relationship
getline(cin, line);
while(getline(cin, line), line != "End"){
sscanf(line.c_str(), "%d,%d", &x, &y);//undirected graph
friends[x].insert(y);
friends[y].insert(x);
}
}
void spfa()
{
//initialize
for(map<int, set<int> >::iterator iter = friends.begin(), eter = friends.end();
iter != eter;
++iter){
dis[iter->first] = friends.size();
inq[iter->first] = false;
}
dis[sponsor] = 0;
q.push(sponsor);
inq[sponsor] = true;
//relax process
set<int>::iterator iter, eter;
while(!q.empty()){
int x = q.front();
q.pop();
inq[x] = false;
iter = friends[x].begin(); eter = friends[x].end();
for(; iter != eter; ++iter){
int y = *iter;
if(dis[y] > dis[x] + 1){
dis[y] = dis[x] + 1;
if(!inq[y]){
q.push(y);
inq[y] = true;
}
}
}
}
}
void separate()
{
map<int, int>::iterator iter = dis.begin(), eter = dis.end();
//there are maxDistance + 1 levels
level.resize(dis.rbegin()->second + 1);
for(; iter != eter; ++iter){
level[iter->second].push_back(iter->first);
}
}
bool allKnown()
{
map<int,int>::iterator iter = toldBy.begin(), eter = toldBy.end();
for(; iter != eter; ++iter){
if(0 == iter->second) return false;
}
return true;
}
void post(int teller, set<int>& peer)
{
set<int>::iterator iter = peer.begin(), eter = peer.end();
map<int,int>::iterator ater = toldBy.begin(), bter = toldBy.end();
for(; iter != eter; ++iter){
ater = toldBy.find(*iter);//*iter might not in this level
if(ater != bter && ater->second == 0) ater->second = teller;
}
}
void undo(int teller, set<int>& peer)
{
set<int>::iterator iter = peer.begin(), eter = peer.end();
map<int,int>::iterator ater = toldBy.begin(), bter = toldBy.end();
for(; iter != eter; ++iter){
ater = toldBy.find(*iter);//*iter might not in this level
if(ater != bter && ater->second == teller) ater->second = 0;
}
}
void dfs(int index, int doPost)
{
if(index < 0){
if(allKnown() && doPost < forwards) forwards = doPost;
return;
}
//if this person do not make a forward
dfs(index - 1, doPost);
//if this person do a forward
post(level[fromLevel][index], friends[level[fromLevel][index]]);
dfs(index - 1, doPost + 1);
undo(level[fromLevel][index], friends[level[fromLevel][index]]);
}
int getMinimumForwards()
{
//because the sponsor's post does not count, we dont need to calculate forwards between level 0 and level 1
//though it is just 1, as we have only one sponsor
int sum = 0, i = 2, n = level.size();
//find minimum forwards needed between each adjacent levels, 1->2, 2->3, ...
for(; i < n; ++i){
//at most each person in this level make a forward
fromLevel = i - 1;
forwards = level[fromLevel].size();
//set known flags of all people in next level to be false
toldBy.clear();
const vector<int>& v = level[i];
for(int j = 0, m = v.size(); j < m; ++j){
toldBy[v[j]] = 0;//insert and set value
}
//DFS to find best result
dfs(level[fromLevel].size() - 1, 0);
sum += forwards;
}
return sum;
}
int main()
{
/* read input */
input();
/* find out each person's shortest distance to sponsor */
spfa();
/* separate each group by distance to sponsor */
separate();
/* find out minimum forwards */
printf("%d\n", getMinimumForwards());
}