头条红人问题解法
9.9日头条算法笔试题第5题。
题目描述
抖音红人:假设用户数为N,有M个关注关系对(A,B).(A,B)表示用户A关注了用户B。关注关系具有传递性。即A关注B,B关注C,那么A也关注C。同时关注的递归传递层数不止2层,可以无限递归。默认自己已经关注了自己,如果输入N=1,则输出也为1。
如果一个用户被所有N个用户直接或间接关注。那么我们认为这个用户是抖音红人。求抖音红人的个数。
用map和set的组合来存储每个人的粉丝群体。`
//递归被关注
void recurFollow(int curId, map<int, set<int>>& fansRelation, vector<bool>& flag,set<int>& tmp)
{
//如果该id没有fans,即一开始就没有将该id录入到fansRelation的表中,在fansRelation的表中就不会找到curId,此时跳出递归
if (fansRelation.find(curId) == fansRelation.end())
{
tmp.insert(curId);
flag[curId] = true;
return;
}
for (int fansId : fansRelation[curId])
{
if (fansId==curId) continue;//遍历自己的情况
if (flag[fansId-1] == true) continue;//标记过的结点不再遍历
tmp.insert(fansId);
flag[fansId-1] = true;//将当前节点进行标记
recurFollow(fansId, fansRelation, flag, tmp);
for (int i : tmp) fansRelation[curId].insert(i);//将tmp中的id全部放入当前id的粉丝群中
}
}
int isHot( map<int, set<int>>& fansRelation, vector<bool>& flag,int N)
{
int count=0;
set<int> tmp;
for (map<int, set<int>>::iterator it= fansRelation.begin();it!=fansRelation.end();it++)
{
for (int i=0;i<N;i++) flag[i] = false;//每次以下一个基点开始遍历时,需要将flag重置
recurFollow(it->first, fansRelation, flag, tmp);
tmp.clear();//清空tmp以备下次使用。
}
//判断有几个人的粉丝量达到了N
for (map<int, set<int>>::iterator it = fansRelation.begin(); it != fansRelation.end(); it++) if (it->second.size() == N) count++;
return count;
}
int main()
{
int N, M;
cin >> N >> M;
//存放用户id和其关注的人
//map<int, set<int>> following;
//用户id和关注他的人
map<int, set<int>> beFollowed;
//存放关系对
vector<vector<int>> fellowPair(M, vector<int>(2));
//标记该节点是否被遍历过
vector<bool> flag(N, false);
for (int i=0;i<M;i++)
{
for (int j=0;j<2;j++)
{
cin >> fellowPair[i][j];
}
//following[fellowPair[i][0]].insert(fellowPair[i][1]);
beFollowed[fellowPair[i][1]].insert(fellowPair[i][0]);
beFollowed[fellowPair[i][1]].insert(fellowPair[i][1]);//默认自己是自己的粉丝
}
cout<<isHot(beFollowed, flag,N);
return 0;
}