pat 1076

1.题意如下:
·在微博中,每个用户可以自发微博,也可以转发(forward)微博,每个用户既可以关注别人,又可以被被人关注。现在给出用户数与有效层数,计算某几个特定用户在发微博之后在某些层内可以带来的最大转发数。
2.思路分析
因为题意假设每个人在看到微博之后,都可以转发,结果是求有效层数内的最大转发人数,所以我们这里可以将问题抽象成一个图,并将其深搜,求出其从根节点出发到自己的最短层数,然后遍历输出即可。
当然,这题最为一般的算法是使用广搜BFS来实现,也较为简单,这里就不给出代码了。
3.代码如下:

#include<cstdio>
#include<vector>
#define maxn 1002
using namespace std;

struct Node{
    int level;//层数
    bool visit;
    vector<int> adj;//相邻节点 
}; 
Node node[maxn]; 
int n,l;

void init(){
    for(int i = 1;i<= n;i++){
        node[i].level = -1;
        node[i].visit = false;
    }
}

//深搜求转发 
void dfs(int root,int level){
    if(node[root].level > level){
        node[root].level = level;       
        node[root].visit = false;
    }
    if(node[root].visit == true || level > l)   return;//若已访问或者访问深度已达,则返回
    else{
        node[root].visit = true;//修改为true 
        node[root].level = level;//修改等级 
        for(int i = 0;i < node[root].adj.size();i++){
            dfs(node[root].adj[i],level+1);
        }
    } 
}

int main(){  
    scanf("%d %d",&n,&l);
    int i ,j;
    int tempNum;//表示被关注的数量 
    int followedUser;
    for(i = 1;i<= n;i++){
        scanf("%d",&tempNum);
        for(j = 0;j< tempNum;j++){
            scanf("%d",&followedUser);
            node[followedUser].adj.push_back(i);//用户i关注followedUser 
        }
    }       
    int userNum;
    int userId;//求其post被转发的数量 
    scanf("%d",&userNum);
    for(i = 0;i< userNum;i++){
        scanf("%d",&userId);
        init();//清0 
        dfs(userId,0);//深搜 

        int count = 0;
        for(j = 1;j <= n;j++){
            if(node[j].level >0 && node[j].level<=l && node[j].visit == true){ 
                count++;
            }
        }printf("%d\n",count);
    }   
} 
/***
7 3
3 2 3 4
0
2 5 6
2 3 1
2 3 4
1 4
1 5
2 2 6

3 3
0
1 1
1 2
1 3
*/

4.注
- 1.本题最需要注意的就是,对于想求出最少的层数问题中,如果不是图,而是树(每个孩子只有一个子节点),我们直接深搜遍历即可;代码如下所示即可:

struct Node{
    int level;//层数
    bool visit;//是否访问
    vector<int> adj;//邻接表
};
void dfs(int root,int level){
    if(node[root].visit == true) return;
    else{
        for(int i = 0;i < node[root].adj.size();i++ ){
            dfs(node[root].adj[i],level+1);
        }
    }
}

但是如果是图(每个孩子有不止一个父节点),我们需要求出最短的层数,这里就需要对层数进行一个遍历更新,代码就应该如下所示:

void dfs(int root,int level){
    if(node[root].level > level){
        node[root].level = level;       
        node[root].visit = false;
    }
    if(node[root].visit == true || level > l)   return;//若已访问或者访问深度已达,则返回
    else{
        node[root].visit = true;//修改为true 
        node[root].level = level;//修改等级 
        for(int i = 0;i < node[root].adj.size();i++){
            dfs(node[root].adj[i],level+1);
        }
    } 
}