The-social-network

题目:

HDU - 4039 The Social Network

The social network system (SNS) helps people to keep connecting with theirfriends. Every user in SNS has a friends list. The user can read news posted bythe users in his friends list. Friend relation is symmetric - if A is a friendof B, B is always a friend of A. 
Another important function in SNS is friend recommendation. One effective wayto recommend friends is recommend by mutual friends. A mutual friend betweentwo users A and B, is a user who is a friend of both A and B. A user can not bea friend of himself. For a specific user A, the system will recommend the userwho is not himself or his friend, and has mutual friends with A. If more thanone such user exists, recommend the one has most mutual friends with A. Ifstill 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 friendrelationship and the number of query. 1 ≤ N, Q ≤ 1000 The following N lineseach contain two different names separated by a single space. Each nameconsisted by only lowercase letters, and its length is less than or equal to15. This means the two users are friends. No friend relationship will be givenmore than once. The following Q lines each describe a query. Each line containone user name. The data guarantee that this name appears at least once in aboveN lines.

Output 
For each case, you should output one line containing “Case k: ” first, where kindicates the case number and counts from one. Then for each query, output oneline, contains one or more names of recommended friends, separate by a singlespace, sorted by alphabetical order. If no persons can be recommended, outputone line contains “-”.

Sample Input 

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 

-


题意:

输入N种朋友关系,指的是这个人互为朋友,查找Q次,查找的是这个人被推荐的朋友。

分析:

被推荐的人要满足一下的条件:A有朋友BCDEBCDE各自除了AA的朋友之外的人中重合度最高的就是要推荐给A的,按照一定顺序排列。这样的话开两个map一个是< string,int>一个是< int,string>,分别对应名字和序号,序号和名字,输入朋友关系的时候,先存入2map,然后再在vector< int>中建立双向节点以供查找。这道题使用BFS在深度为二的时候,将所有出现过的人都以下标的形式存入一个数组中表示次数,并且更新出现次数最多的,最后出现最多的放入set然后输出就OK



代码如下:

#include<cstdio>

#include<iostream>

#include<map>

#include<vector>

#include<cstring>

#include<queue>

#include<set>

usingnamespacestd;

 

map<string, int> ID;       //名字查找序号(用于存储)

map<int, string> RD;       //序号查找名字(用于输出)

vector<int> e[2005];      //建立节点关系

 

struct ff

{

    int id;        //当前ID

    int step;        //查找深度

};

 

int time[2005];       //出现次数

int mx;        //出现最大次数

 

void bfs(int i)       //传入要查找的人

{

    queue<ff> q;

    q.push(ff{i, 0});        //深度为1IDf推入队列

    while(!q.empty())

    {

        ff v = q.front();

        q.pop();

        if(v.step < 2)        //深度小于2

        {

            for(auto &k : e[v.id])

            {

                if(v.step == 0)        //深度为0时直接推入

                {

                    q.push(ff{k, v.step + 1});

                }

                if(v.step == 1 && k !=i)        //深度为1时推入要求ID不与被查询人相同,就是不把自己推荐给自己

                {

                    int ll = 0;

                    for(auto &l : e[i])    //确保被推荐人不是被查询人的朋友,即不把被查询人的朋友推荐给被查询人

                    {

                        if(k == l)

                            ll++;

                    }

                    if(ll == 0)    //同时满足上面两点就入队

                        q.push(ff{k, v.step + 1});

                }

            }

        }

        if(v.step == 2)        //深度为2,就是符合条件的人

        {

            time[v.id]++;        //查找出现次数最多的

            mx = (mx > time[v.id]) ? mx :time[v.id];

        }

    }

    while(!q.empty())   q.pop();

}

 

int main()

{

    int T;

    scanf("%d", &T);

    for(int i = 0; i < T; i++)

    {

 

        int N, Q;

        printf("Case %d:\n", i + 1);

        cin >> N >> Q;

        //cout << "Case " <<i + 1 << ": " << endl;

        int cnt = 0;

        for(int j = 0; j <= 2 * N; j++)

            e[j].clear();

        ID.clear();

        RD.clear();

        for(int j = 0; j < N; j++)

        {

            string str1, str2;

            cin >> str1 >> str2;

            if(!ID[str1])

            {

                ID[str1] = ++cnt;

                RD[cnt] = str1;

            }

            if(!ID[str2])

            {

                ID[str2] = ++cnt;

                RD[cnt] = str2;

            }

            int u = ID[str1], v = ID[str2];

            e[u].push_back(v);

            e[v].push_back(u);

        }

        for(int j = 0; j < Q; j++)

        {

            string str3;

            cin >> str3;

            memset(time, 0, sizeof(time));

            mx = 0;        //初始化为0

            bfs(ID[str3]);

            if(mx == 0)        //没有可以推荐的就输出-

            {

                cout << "-" << endl;

            }

            else

            {

                set<string> ss;

                for(int k = 0; k < 2005; k++)

                {

                    if(time[k] == mx)

                        ss.insert(RD[k]);

                }        //上述操作是将出现次数最多的都放入set

                for(set<string>::iterator item = ss.begin(); item!= ss.end(); item++)

                {

                    set<string>::iterator item2 = item;

                    item2++;

                    if(item2 != ss.end())   //控制输出格式

                        cout << *item << " ";

                    if(item2 == ss.end())

                        cout << *item << endl;

                }

            }

        }

    }

    return0;

}


flighting!!!


一定要注意格式,一定要注意格式,一定要注意格式!!!重要的事说三遍,为了一个格式的问题改了一上午……令人绝望。

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值