【map+字典序】hdu 4039 The Social Network

【map+字典序】hdu 4039 The Social Network

题目链接:hdu 4039 The Social Network

题目大意

模拟一个社交网络系统,先给你n个朋友关系,对每个人,系统会推荐给他一些人给他交朋友,系统推荐的是:他朋友的朋友且与他不是朋友,而且只推荐他最多共同朋友的朋友,如果会推荐多个,按照字典序从小到大输出,如果一个也不推荐输出“-”

这里写图片描述
这里写图片描述
这里写图片描述

熟练map映射:字典序本身map容器里的关键字就是按照字典序存储的,所以最后只要遍历一遍容器,把满足题意的字符串输出即可。


说一下思路

  • (1)首先vector建树,无向图,map对字符串作映射,相当于编号。注意vector存储空间是两倍的点数,笔者在这里初始化WA了!QAQ;
  • (2)暴力查找O(N^2),数据量不大的:首先标记ok1[]—与A是朋友的true;接着标记ok2,表示A的朋友的朋友,for两圈,期间维护一个最大值dp-与A的有共同朋友的最大值;最后,遍历Map,查找是否A的朋友的朋友、且与A不是朋友、且有A有最多的共同朋友,,好绕口(ㄒoㄒ),找到后就输出即可

这里写图片描述


参考代码

/*====================================*\
|*   map + 字典序 +  图的邻接表存储       *|
\*====================================*/
/*Author:Hacker_vision*/
#include<bits/stdc++.h>
#define clr(k,v) memset(k,v,sizeof(k))
#define eps 1e-8
#define ll long long
using namespace  std;

const int _max = 1e3 + 10;
int n,Q,dp,ok2[_max<<1];
bool ok1[_max<<1];
string s1,s2;
vector<int>child[_max<<1];//vector邻接表存储图,2倍边数~!!
map<string,int>mp;
map<string,int>::iterator it;

bool query(string s){//暴力查找O(N^2),v是u的朋友,x是v的朋友且不是u的朋友
  int u = mp[s];//字符串s对应的编号
  clr(ok1,0);//ok1[x]表示x是不是A的朋友
  for(int i = 0;i < child[u].size(); ++ i)//标记u的所有朋友
        ok1[child[u][i]] = true;
        ok1[u] = true;
  clr(ok2,0);//ok2[x]表示x与A有几个共同朋友
  dp = 0;//dp:与A有相同朋友的最大值,且与A并不是朋友
  for(int i = 0;i < child[u].size(); ++ i){
    int v = child[u][i];
    for(int j = 0;j < child[v].size(); ++ j){
       int x = child[v][j];
       if(ok1[x]) continue;//如果与A是朋友,没有意思,不必处理
       ok2[x] ++ ;
       dp = max(dp,ok2[x]) ;
    }
  }
   bool ok = true;//控制输出格式
   for(it = mp.begin();it != mp.end(); ++ it)//map容器本身就字典序排好了
    if(ok1[it->second]==false&&ok2[it->second]==dp&&ok2[it->second]) {
        if(ok) {cout<<it->first;ok = false;}
        else cout<<" "<<it->first;
    }
  if(!ok) {puts("");return true;}
  return false;
}

int main(){
  #ifndef ONLINE_JUDGE
  freopen("input.txt","r",stdin);
  #endif // ONLINE_JUDGE
  int T;cin>>T;int cnt = 1;
  while(T--){
    scanf("%d%d",&n,&Q);
    mp.clear();
    for(int i = 1; i <= 2*n; ++ i) child[i].clear();//初始化
    int top = 1;
    for(int i = 0;i < n; ++ i){
        cin>>s1>>s2;
        if(!mp[s1]) mp[s1] = top++;
        if(!mp[s2]) mp[s2] = top++;//字符串作map映射
        child[mp[s1]].push_back(mp[s2]);
        child[mp[s2]].push_back(mp[s1]);//无向图建立
    }
    printf("Case %d:\n",cnt++);
    for(int i = 0; i < Q; ++ i){
         cin>>s1;
         if(!query(s1)) puts("-");
    }
  }
  return 0;
}
  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值