1076 Forwards on Weibo
大致题意就是给出N组数据构造一个无向连通图,然后从顶点U开始统计出 L层 内(除自己外)所有结点的个数。
若使用DFS很容易出问题,比如:
情况一,图中有环。如果整个环上的结点都被访问并标记了,那么与环相连的其它路径上的结点可能无法因为路径上的某个结点被标记了,导致其无法被访问到。
情况二,可能会重复统计某个结点的情况。
如果解决了上述一、二情况,但是DFS写不够好,就会超时~~
所以在解答 从某个结点出发,统计L层内结点个数的问题,建议用BFS求解。
1 #include<iostream> 2 #include<vector> 3 #include<queue> 4 using namespace std; 5 6 const int maxn = 1010; 7 struct Node { 8 int id; 9 int layer; 10 Node(int _id,int _layer):id(_id),layer(_layer) {} 11 }; 12 vector<Node> adj[maxn]; //邻接表 13 bool inq[maxn] = {false};//标记顶点是否入队过的数组 14 int n,L,m,t,k; 15 int BFS(int s) { //图的DFS 16 int cnt = 0;//统计从起点S开始 L层内结点的个数(不包含起点S) 17 //第一步,定义队列并入队 18 queue<Node> q; 19 q.push(Node(s,0)); 20 inq[s] = true;//标记已入过队 21 //第二步,判断队列非空 22 while(!q.empty()) { 23 //第三步,访问队首元素并出队 24 Node top = q.front(); 25 int u = top.id; 26 q.pop(); 27 //第四步,下一层元素入队 28 for(int i = 0; i < adj[u].size(); ++i) { 29 Node next = adj[u][i]; 30 next.layer = top.layer+1; 31 if(inq[next.id] == false && next.layer <= L) { 32 q.push(next); 33 inq[next.id] = true;//标记已入过队 34 cnt++; 35 } 36 } 37 } 38 return cnt; 39 } 40 int main() { 41 cin>>n>>L; 42 for(int i = 1 ; i <= n; ++i) { 43 cin>>m; 44 for(int j = 0 ; j < m; ++j) { 45 cin>>t; 46 adj[t].push_back(Node(i,0)); 47 } 48 } 49 cin>>k; 50 for(int i = 0 ; i < k; ++i) { //k次查询 51 fill(inq+1,inq+1+n,false); //初始化标记数组 52 cin>>t; //起点 53 printf("%d\n",BFS(t)); 54 } 55 return 0; 56 }
目前DFS求不出来。。。
1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn = 1010; 7 vector<int> adj[maxn]; //邻接表 8 bool visited[maxn] = {false};//标记顶点是否被访问过的数组 9 10 int n,L,m,t,k,cnt; 11 void DFS(int u,int level) { //图的DFS 12 visited[u] = true; //标记已访问 13 for(int i = 0; i < adj[u].size(); ++i) { 14 int v = adj[u][i]; 15 if(visited[v] == false && level+1 <= L) { 16 cnt++; 17 DFS(v,level+1); 18 } 19 } 20 } 21 int main() { 22 cin>>n>>L; 23 for(int i = 1 ; i <= n; ++i) { 24 cin>>m; 25 for(int j = 0 ; j < m; ++j) { 26 cin>>t; 27 adj[t].push_back(i); 28 } 29 } 30 cin>>k; 31 for(int i = 0 ; i < k; ++i) { 32 cin>>t; 33 cnt = 0; 34 fill(visited+1,visited+1+n,false); //初始化标记数组 35 DFS(t,0); 36 printf("%d\n",cnt); 37 } 38 return 0; 39 }
修改了一下代码,又强行DFS了一次,逻辑没问题,但是超时了~~。
1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn = 1010; 7 vector<int> adj[maxn]; //邻接表 8 bool visited[maxn] = {false};//标记顶点是否被访问过数组,控制DFS方向 9 bool visited2[maxn] = {false};//标记顶点是否只被访问过一次 10 int n,L,m,t,k,cnt; 11 void DFS(int u,int level) { //图的DFS 12 visited[u] = true; //标记已访问 13 for(int i = 0; i < adj[u].size(); ++i) { 14 int v = adj[u][i]; 15 if(visited[v] == false && level+1 <= L) { 16 if(visited2[v] == false) { //仅能被访问一次 17 visited2[v] = true; 18 cnt++; 19 } 20 DFS(v,level+1); 21 } 22 } 23 visited[u] = false; //回退前,撤销标记 24 } 25 int main() { 26 cin>>n>>L; 27 for(int i = 1 ; i <= n; ++i) { 28 cin>>m; 29 for(int j = 0 ; j < m; ++j) { 30 cin>>t; 31 adj[t].push_back(i); 32 } 33 } 34 cin>>k; 35 for(int i = 0 ; i < k; ++i) { 36 cin>>t; 37 cnt = 0; 38 fill(visited+1,visited+1+n,false); 39 fill(visited2+1,visited2+1+n,false); 40 visited2[t] = true; 41 DFS(t,0); 42 printf("%d\n",cnt); 43 } 44 return 0; 45 }