SDNU-BFS——E

来源:互联网 发布:阿里云服务器转让 编辑:程序博客网 时间:2024/04/28 06:51
The social network system (SNS) helps people to keep connecting with their friends. Every user in SNS has a friends list. The user can read news posted by the users in his friends list. Friend relation is symmetric - if A is a friend of B, B is always a friend of A.

Another important function in SNS is friend recommendation. One effective way to recommend friends is recommend by mutual friends. A mutual friend between two users A and B, is a user who is a friend of both A and B. A user can not be a friend of himself. For a specific user A, the system will recommend the user who is not himself or his friend, and has mutual friends with A. If more than one such user exists, recommend the one has most mutual friends with A. If still a tie exists, output all of them.
Input
The first line is a integer T (T≤100), the number of test case.
The beginning of each test case is two integers N and Q, the number of friend relationship and the number of query. 1 ≤ N, Q ≤ 1000
The following N lines each contain two different names separated by a single space. Each name consisted by only lowercase letters, and its length is less than or equal to 15. This means the two users are friends. No friend relationship will be given more than once.
The following Q lines each describe a query. Each line contain one user name. The data guarantee that this name appears at least once in above N lines.
Output
For each case, you should output one line containing “Case k: ” first, where k indicates the case number and counts from one. Then for each query, output one line, contains one or more names of recommended friends, separate by a single space, sorted by alphabetical order. If no persons can be recommended, output one line contains “-”.
Sample Input
1
10 11
hongshu digua
yingying hongshu
xmm hongshu
huaxianzi xmm
tangjiejie huaxianzi
xhmz yingying
digua xhmz
zt tangjiejie
xmm lcy
notonlysuccess ljq
hongshu
digua
yingying
xmm
huaxianzi
tangjiejie
xhmz
zt
lcy
notonlysuccess
ljq

Sample Output
Case 1:
xhmz
yingying
digua
digua tangjiejie yingying
hongshu lcy zt
xmm
hongshu
huaxianzi
hongshu huaxianzi
-
-


哇,这个题可真的是不错的,听队长讲了一遍后,又借鉴了下网上大佬的思路与实现代码,才磕磕绊绊的AC(一下午吧,我真的是太水了)


首先构图就是一个难点,我们构的图都是数啊,这全是字符串还是人名真的是(XXX)太巧妙了

用两个map就像数学中的映射一样,把每一个输入进的字符串都映射一个ID,再弄一个反映射(reID)映射回去通过数字找到人名

na——通过人名找,ID me通过ID找人名最后再确立二者间的互相朋友关系(vector 二维动态数组)

if(na[str1] == 0){na[str1] = cnt++;me[cnt - 1] = str1;}if(na[str2] == 0){na[str2] = cnt++;me[cnt - 1] = str2;}e[na[str1]].push_back(na[str2]);e[na[str2]].push_back(na[str1]);

这样图就构成了

接下来开始找朋友~~

一共就找两层朋友关系

eg:一层 找到A 的朋友B , C   二层 :找到 B 的朋友C D E,找到 C 的朋友 B D F

因为B C 是 A 的一层关系 所以不会推荐 又二层关系中 D 的次数最多,所以最终会推荐给A 

大体就是上述过程

步数确定就实现bfs吧

首先有队列:一个是指向一个是步数

虽然就两步但还是得分开考虑

bfs 找完所有的一层关系,vis数组全部标记,并更新步数

找完一层后,队列里全是一层关系,且步数为一

所以开始找二层关系(注意二层关系中除了判断是不是一层关系外还得判断是不是节点关系就是0层boss本身)

if(v != na[str1] && !vis[v])

一边用一个retmap统计二层可用关系中各个人出现的次数

一边用fmax计数并返回出现次数最多的ID

最后遍历ret看看是不是有多个推荐(ps:fc的设置只是为了我匹配输出格式)
如果没有可以推荐的对象,fmax的初始值不会更新这也好判断


#include<iostream>#include<map>#include<cstdio>#include<cstdlib>#include<string>#include<queue>#include<memory.h>using namespace std;string str1,str2;int fmax = -999;int caase = 0;const int maxn = 2000 + 10;vector<int> e[maxn];map<string,int> na;map<int,string> me;map<string,int> ret;bool vis[maxn];int cnt;struct fd{int temp;int step;}fr;queue<fd> myf;bfs(fd fr){while(!myf.empty()){fr = myf.front();//cout<<fr.temp<<"\n"<<me[fr.temp]<<"\n"<<fr.step<<endl;myf.pop();if(fr.step == 0){for(auto &v : e[fr.temp]){//cout<<v<<endl;vis[v] = 1;fd fr2;fr2.step = 1;fr2.temp = v;//cout<<fr.temp<<endl;myf.push(fr2);}}else if(fr.step == 1){for(auto &v : e[fr.temp]){if(v != na[str1] && !vis[v]){ret[me[v]]++;if(ret[me[v]] > fmax){fmax = ret[me[v]];}} }}else return true;}return true;}int main(){int t;scanf("%d",&t);while(t--){caase++;int n,f;memset(vis,0,sizeof(vis));na.clear();me.clear();ret.clear();while(!myf.empty()){myf.pop();}scanf("%d%d",&n,&f);int i,j,k,l;for(i = 0;i < maxn;i++){e[i].clear();}cnt = 1;for(i = 0;i < n;i++){cin>>str1>>str2;if(na[str1] == 0){na[str1] = cnt++;me[cnt - 1] = str1;}if(na[str2] == 0){na[str2] = cnt++;me[cnt - 1] = str2;}e[na[str1]].push_back(na[str2]);e[na[str2]].push_back(na[str1]);}printf("Case %d:\n",caase);for(i = 0;i < f;i++){cin>>str1;ret.clear();while(!myf.empty()){myf.pop();}memset(vis,0,sizeof(vis));fr.temp = na[str1];//cout<<fr.temp<<endl;fr.step = 0;myf.push(fr);bfs(fr);int fc = 0;map<string,int>::iterator it;for(it = ret.begin();it != ret.end();it++){if((*it).second == fmax){if(fc == 1){cout<<" "<<(*it).first;} else{fc = 1;cout<<(*it).first;}}}if(fmax == -999) {cout<<"-"<<endl;}else if(fc == 1){cout<<endl;}//cout<<fmax<<endl;fmax = -999;}}return 0;}