【1076】Forwards on Weibo (圖BFS)
阿新 • • 發佈:2021-02-02
技術標籤:BFS和DFS
1.題目
https://pintia.cn/problem-sets/994805342720868352/problems/994805392092020736
微博轉發背景,給出N個使用者的關注情況(關注的人有哪些)和轉發層數上限L,用最初發布訊息的使用者編號進行查詢,求在轉發層數上限內訊息最多會轉發的使用者數。
2.思路
同一層可以有多個粉絲進行轉發,所以顯然用BFS合適。
不過寫的時候出現了是三個傻逼BUG,實在該打!
(1)在輸入點的座標的for迴圈時候忘記結點的編號是1~N,而不是0,所以不能習慣地對for迴圈裡面的i從0開始遍歷;
(2)由於我一開始搞的crossnum
是個全域性變數,每次查詢後不要忘記對其進行清零,或者就定義再BFS裡面也行(然後搞個返回值額)就不需要清零了;
Node start=Node(i,0)
一開始Node的第一個引數寫成了a了,導致錯誤。題目給出的是當前i結點的關注的人a,不要對下標寫反了,應該是
adj[a].push_back(start)
。
另外
(1)為了減少程式碼行數,可以在結構體內使用建構函式,而初始化可以用Node start=Node(i,0)
。
結構體內建構函式的三種方法。
(2)memset
的標頭檔案是<string.h>,而不是標頭檔案< string>。
最好不用DFS:
(1)由於可能成環,因此必須控制每個使用者只能轉發訊息一次(即遍歷時只能訪問一次);
(2)用DFS易出錯,因有一種情況:一個使用者X在第i次被訪問,但此時已經達到轉發層數上限(故無法繼續遍歷), 但使用者可以通過另一條路徑更快訪問到(如下圖:1到5有2條路徑,轉發上限為L=3,即有一條路徑合法)。
3.完整程式碼
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<string.h>//memset的標頭檔案
using namespace std;
const int N=1010;
int maxxx;//最大傳播層數閾值
int crossnum=0;
//鄰接表儲存
struct Node{
int v;
int layer;
Node(int a,int b):v(a),layer(b){ }//建構函式
Node(int a){
v=a;
}
};
vector<Node>adj[N];
bool inq[N]={false};
int BFS(int index){
queue<Node>q;
Node start=Node(index,0);
q.push(start);
inq[start.v]=true;
while(!q.empty()){
Node topNode=q.front();
q.pop();
int u=topNode.v;
for(int i=0;i<adj[u].size();i++){
Node next=adj[u][i];
next.layer=topNode.layer+1;
if(inq[next.v]==false&& ((next.layer)<=maxxx)){
q.push(next);
inq[next.v]=true;
crossnum++;
}
}
}
return crossnum;
}
int main(){
int vnum;
scanf("%d%d",&vnum,&maxxx);
//輸入階段(儲存圖)
for(int i=1;i<=vnum;i++){//注意結點編號從1開始,所以i非0開始
int n1;
scanf("%d",&n1);//i號使用者關注的人數
for(int j=0;j<n1;j++){
int a;
scanf("%d",&a);//i號使用者關注的人的編號
Node start=Node(i,0);//一開始Node的第一個引數寫成了a了,導致錯誤
adj[a].push_back(start);
}
}
//最後一行(查詢步驟)
int qnum;
scanf("%d",&qnum);
for(int i=0;i<qnum;i++){
memset(inq,false,sizeof(inq));
crossnum=0;//每次輸出之後需要清零
int startnode;
scanf("%d",&startnode);
BFS(startnode);
printf("%d\n",crossnum);
//crossnum=0;//每次輸出之後需要清零
}
system("pause");
}