D-小H和游戏

小H和游戏

http://www.nowcoder.com/questionTerminal/fe8b439bf6ed4d3ea210cde06756f71c

这个题解实话说都是抄的其他dl的题解
写这个的用意主要是为了便于自己理解以及把dl觉得显而易见的写出来

前导
一:
整合树,建立数组fa[N]来确定每个点的父节点
Method one: vector

vector<int> q[N];
inline void dfs(int x, int f) {//确定父节点
    fa[x] = f;
    for (auto i : q[x]) { 
        if (i == f) continue;
        else dfs(i, x);
    }
        //for(auto i:q[x]) --> vector<int>::iterator it; 
        //for(it=q[x].begin();it!=q[x].end();++it) 大概便于理解就是这意思了
}
inline void init() {
    for(int i=1;i<n;++i) {
        int x, y;
        cin >> x >> y;
        q[x].push_back(y); //存储与x相邻的点
        q[y].push_back(x); //存储与y相邻的点
    }
}

Method two : 前向星(等会儿补)

二:
解释数据中部分变量意思
cnt[x][0] --> x本身
cnt[x][1] --> x儿子
cnt[x][2] --> x儿子的儿子
求点x被波及到次数可化为: cnt[x][0]+cnt[fa[x]][1]+cnt[fa[fa[x]]][2]
x被波及大致有以下:
x本身,x儿子,x儿子的儿子,x父亲,x的父亲的父亲,x的兄弟(x父亲的儿子)

假使轰炸x的儿子y,则x被波及可表述为 ++cnt[fa[y]][0]-->++cnt[x][0]
假使轰炸x的孙子z,则x被波及可表述为 ++cnt[fa[fa[z]]][0]-->++cnt[x][0]
-->轰炸儿子孙子可直接在cnt[x][0]中反映出来
假使轰炸x的父亲r,则x被波及可表述为 ++cnt[r][1]-->++cnt[fa[x]][1]
假使轰炸x的爷爷g,则x被波及可表述为 ++cnt[g][2]-->++cnt[fa[fa[x]]][2]
假使轰炸x的兄弟v,则x被波及可表述为 x(v父亲的儿子) ++cnt[fa[x]][1]
计算代码:

while (m--) {
        int x;
        cin >> x;
        //cnt[x][0]--本身 cnt[x][1]--儿子 cnt[x][2]--儿子的儿子
        ++cnt[x][1], ++cnt[x][2];   //x的儿子被波及,x的儿子的儿子被波及
        ++cnt[fa[x]][0], ++cnt[fa[x]][1];  //x的父亲被波及,x父亲的儿子被波及(包括x)
        ++cnt[fa[fa[x]]][0];  //x的父亲的父亲被波及
        cout << cnt[x][0] + cnt[fa[x]][1] + cnt[fa[fa[x]]][2] << "\n"; 
    }         

三:
总代码

#pragma warning (disable :4996)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = cos(-1.0);
const double eps = 1e-10;
#define For(i,n,m) for(int i=n;i<=m;++i)

const int N = 75e4 + 10;
int n, m, a[N], fa[N];
int cnt[N][3];
vector<int> q[N];
inline void dfs(int x, int f) {//确定父节点
    fa[x] = f;
    for (auto i : q[x]) {
        if (i == f) continue;
        else dfs(i, x);
    }
}
inline void init() {
    cin >> n >> m;
    For(i, 1, n - 1) {
        int x, y;
        cin >> x >> y;
        q[x].push_back(y);
        q[y].push_back(x);
    }
}
inline void solve() {
    dfs(1, 0);
    while (m--) {
        int x;
        cin >> x;
        //cnt[x][0]--本身 cnt[x][1]--儿子 cnt[x][2]--儿子的儿子
        ++cnt[x][1], ++cnt[x][2];   
        ++cnt[fa[x]][0], ++cnt[fa[x]][1]; 
        ++cnt[fa[fa[x]]][0]; 
        cout << cnt[x][0] + cnt[fa[x]][1] + cnt[fa[fa[x]]][2] << "\n"; 
    }
}
int main() {
    ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
    init();
    solve();
    return 0;
}
全部评论

相关推荐

程序员花海_:实习和校招简历正确格式应该是教育背景+实习+项目经历+个人评价 其中项目经历注意要体现业务 实习经历里面的业务更是要自圆其说 简历模板尽可能保持干净整洁 不要太花哨的
点赞 评论 收藏
分享
不知道怎么取名字_:两个方向 1.简历针对性准备下 2.面试前也需要准备的 主要还是要看各个公司需求,看公司行业和岗位描述,那里面已经写了对技术的需求,一份简历,不可能和所有嵌入式岗位都匹配的
投递北京经纬恒润科技股份有限公司等公司10个岗位
点赞 评论 收藏
分享
评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务