Weibo is known as the Chinese version of Twitter. One user on Weibo may have many followers, and may follow many other users as well. Hence a social network is formed with followers relations. When a user makes a post on Weibo, all his/her followers can view and forward his/her post, which can then be forwarded again by their followers. Now given a social network, you are supposed to calculate the maximum potential amount of forwards for any specific user, assuming that only L levels of indirect followers are counted.
Input Specification:
Each input file contains one test case. For each case, the first line contains 2 positive integers: N (≤1000), the number of users; and L (≤6), the number of levels of indirect followers that are counted. Hence it is assumed that all the users are numbered from 1 to N. Then N lines follow, each in the format:
M[i] user_list[i]
where M[i] (≤100) is the total number of people that user[i] follows; and user_list[i] is a list of the M[i] users that followed by user[i]. It is guaranteed that no one can follow oneself. All the numbers are separated by a space.
Then finally a positive K is given, followed by K UserID’s for query.
Output Specification:
For each UserID, you are supposed to print in one line the maximum potential amount of forwards this user can trigger, assuming that everyone who can view the initial post will forward it once, and that only L levels of indirect followers are counted.
Sample Input:
7 3
3 2 3 4
0
2 5 6
2 3 1
2 3 4
1 4
1 5
2 2 6
Sample Output:
4
5
给定一个图网络(N)和一个转发层数限制,最多可以传播几层(L),求一条微博在L内最多可以被多少个用户转发,主体上使用BFS的思路,一层层的拓展直到到达L层
代码如下:
#include
#include
#include
#include
using namespace std;
const int maxn=1005;
int N,L;
vector<int> list[maxn];
bool vis[maxn] = {false};
int currentLayer=0;
int times=0;
int lastExtendNum[10];
void BFS(int v){
queue<int> q;
q.push(v);
vis[v]=true;
lastExtendNum[currentLayer]=1;
while(!q.empty()&¤tLayer<L){
// printf("NO %d\n",currentLayer+1);
for(int m=0;m<lastExtendNum[currentLayer];m++){
int k = q.front();
q.pop();
for(int i=0;i<list[k].size();i++){
if(vis[list[k][i]]==false){
times++;
// printf("%d ",list[k][i]);
vis[list[k][i]]=true;
q.push(list[k][i]);
lastExtendNum[currentLayer+1]+=1;
}
}
}
// printf("\n");
currentLayer++;
}
}
int main(){
scanf("%d%d",&N,&L);
int M;
for(int i=1;i<=N;i++){
scanf("%d",&M);
int node;
for(int k=0;k<M;k++){
scanf("%d",&node);
list[node].push_back(i);
}
}
// printf("5号节点:\n");
// for(int i=0;i
// printf("%d ",list[5][i]);
// }
// printf("\n");
int queryNum;
scanf("%d",&queryNum);
for(int i=0;i<queryNum;i++){
int queryId;
scanf("%d",&queryId);
currentLayer=0;
times=0;
for(int k=1;k<=N;k++){
vis[k]=false;
}
memset(lastExtendNum,0,sizeof(lastExtendNum));
BFS(queryId);
printf("%d\n",times);
}
}
while(!q.empty()&¤tLayer
这导致了内部还需要一次循环来控制每轮取出的个数,否则每轮只会取一个数进行拓展,这样只能通过query=2的查询(因为2中每次只会拓展出一个节点),6通不过,6的第二轮拓展出了3个节点,若不加内部一层循环,只会拓展第二轮的一个节点,为空,直接结束,导致最后未到达 7 号节点,次数-1;但是好处是不需要再维护node结构体;
#include
#include
#include
using namespace std;
int n, l, m, k;
struct node{ //带层数的广度优先
int id, layer;
};
vector<vector<int>> v; //大小用resize声明则元素类型需要如此定义
int BFS(node tnode); //返回最大转发量
int main()
{
cin >> n >> l;
v.resize(n+1);
//生成图的邻接表
for ( int i=1; i<=n; i++ ){
cin >> m;
for ( int j=0; j<m; j++ ){
int tmp;
cin >> tmp;
v[tmp].push_back(i); //tmp→(关注)→i
}
}
//统计k个用户的粉丝量
cin >> k;
int tid;
for ( int i=0; i<k; i++ ){
cin >> tid;
node tnode = {tid, 0}; //从直接粉丝开始算第一层
//遍历指定顶点所在连通块
printf("%d\n", BFS(tnode));
}
return 0;
}
int BFS(node tnode){
bool inq[1010] = {false}; //入队情况
queue<node> q;
q.push(tnode); //初始元素入队
inq[tnode.id] = true; //针对id标记入队情况
int cnt = 0; //计算转发量
while( !q.empty() ){
node top = q.front(); //取出队首元素
q.pop(); //队首元素出队
int topid = top.id; //队首元素id
for ( int i=0; i<v[topid].size(); i++ ){
int nextid = v[topid][i]; //邻接顶点id
if ( inq[nextid]==false && top.layer<l ){ //有层次限制
node next = {nextid, top.layer+1};
q.push(next); //往邻接顶点遍历,层次+1
inq[next.id] = true; //标记
cnt++;
}
}
}
return cnt;
}
最外层只需判断队列是否为空即可,内部通过node.layer是否超过L来选择是否可以达到下一个节点。队列内不需要两层循环。
两种方法,两种思路,各有优势。