Problem C: Friends----dfs记忆化搜索

本文介绍了一种通过记忆化深度优先搜索算法解决特定问题的方法,该问题是在一棵表示人际关系的树中找出每个个体能在五步内接触的所有可能的朋友数量。

Problem C: Friends

Time Limit: 1 Sec   Memory Limit: 1280 MB
Submit: 107   Solved: 20
[ Submit][ Status][ Web Board]

Description

    In a country, the relationship between people can be indicated by a tree. If two people are acquainted with each other, there will be an edge between them. If a person can get in touch with another through no more than five people, we should consider these two people can become friends. Now, give you a tree of N people’s relationship. ( 1 <= N <= 1e5), you should compute the number of who can become friends of each people?  

Input

    In the first line, there is an integer T, indicates the number of the cases.
    For each case, there is an integer N indicates the number of people in the first line.
   

In the next N-1 lines, there are two integers u and v, indicate the people u and the people

v are acquainted with each other directly. People labels from 1.  

Output

    For each case, the first line is “Case #k :”, k indicates the case number.

    In the next N lines, there is an integer in each line, indicates the number of people who can become the ith person’s friends. i is from 1 to n.  

Sample Input

1 
8 
1 2 
2 3 
3 4 
4 5 
5 6 
6 7 
7 8

Sample Output

Case #1:
6
7
7
7
7
7
7
6
题目链接:http://acm.hzau.edu.cn/problem.php?cid=1029&pid=2


题目的意思是五步以内关系的人可以成为朋友,我们要算出每个人可以有多少个朋友。

我一开始用了dfs暴搜,然后华丽丽的tle了,然后我就用记忆化搜索,然后华丽丽的wa了,我的内心!……*,交了三发,都没有过,比赛结束后卡到了6题榜首,我是多么想7题啊。。。

赛后看了题解,就是一个dfs记忆化搜索,记录六步(大于六步的算六步)的人数,然后搜,当时这么想过,以为很难搞,还要算重复,我就GG,赛后的题解就是这么搞得,看了代码,我的码力还是不够啊,我觉得我当时就是坚持下去用这种方法敲了,照样敲不出来,哎。

大牛链接:http://blog.youkuaiyun.com/hnust_derker/article/details/70549607

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int maxn=1e5+10;
int pre[maxn];
vector<int >G[maxn];
int son[maxn][7];
void dfs(int fa[7],int u){
    int fat=fa[5];
    pre[u]=fat;
    for(int i=0;i<=5;i++){
        int f=fa[i];
        son[f][6-i]++;
    }
    int nf[7]={fa[1],fa[2],fa[3],fa[4],fa[5],u};
    for(int i=0;i<(int )G[u].size();i++){
        int v=G[u][i];
        if(v==fat)
            continue;
        dfs(nf,v);
    }
}
int main(){
    int t;
    int cnt=0;
    scanf("%d",&t);
    while(t--){
        cnt++;
        int n;
        scanf("%d",&n);
        memset(son,0,sizeof(son));
        for(int i=0;i<=n;i++){
            son[i][0]=1;
            G[i].clear();
            for(int j=1;j<7;j++){
                son[i][j]=0;
            }
        }
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        int f[7]={0,0,0,0,0,0};
        dfs(f,1);
        printf("Case #%d:\n",cnt);
        for(int i=1;i<=n;i++){
            int ans=0;
            for(int j=0;j<=6;j++){
                ans+=son[i][j];
            }
            int u=i;
            for(int j=1;j<=6;j++){
                int v=u;
                u=pre[u];
                if(u==0){
                    break;
                }
                for(int k=0;k<=6-j;k++){
                    ans+=son[u][k];
                }
                for(int k=0;k<=6-j-1;k++){
                    ans-=son[v][k];
                }
            }
            printf("%d\n",ans-1);
        }
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值