wannafly10 c题 dfs+思路

16 篇文章 0 订阅
4 篇文章 0 订阅

这道题开始先直接dfs,然后tle了,然后换汤不换药bfs一遍,又tle了。看了别人的思路,恍然大悟。

TLE思路:建图,然后对于每次轰炸,以轰炸的节点为根进行dfs,更新相邻节点损毁的次数。

TLE写起来简单粗暴,但结果也很粗暴。。。

AC思路:建图后先进行一次dfs(以编号为1的节点为根,将无根树转为有根树)找出每个节点对应的父节点,然后根据父子关系,爷孙关系以及兄弟关系,推出节点的损毁次数。(兄弟被轰炸产生的损毁较容易i被漏掉)

两种思路对比以下,第二种思路确实剪枝了许多,因为需要查询的只有被轰炸的点,所以每次直接直接计算出该点的次数即可,无需全部点更新

#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1e6+50;
int n,q,u,v,boom1[maxn],boom2[maxn],boom3[maxn],boom[maxn],pa[maxn];
///boom1[x]表示的是 炸x点时 直接 波及到的爸爸节点,
///boom2则表示 直接 波及到的爷爷节点,
///boom3表示波及到的兄弟节点,记录在父节点上,
///boom表示这个点直接被炸的次数
vector<int> node[maxn];
 
 
void dfs(int id,int fa){
    for(int i=0;i<node[id].size();i++){
        int son=node[id][i];
        if(son==fa) continue;
        pa[son]=id;
        dfs(son,id);
    }
}
 
int main(){
    while(scanf("%d%d",&n,&q)!=EOF){
        memset(boom,0,sizeof(boom));
        memset(boom1,0,sizeof(boom1));
        memset(boom2,0,sizeof(boom2));
        memset(boom3,0,sizeof(boom3));
        memset(node,0,sizeof(node));
        memset(pa,0,sizeof(pa));
        for(int i=0;i<n-1;i++){
            scanf("%d%d",&u,&v);
            node[u].push_back(v);
            node[v].push_back(u);
        }
        dfs(1,0);///递归得出每个点的父节点
        for(int i=0;i<q;i++){
            int temp;
            scanf("%d",&temp);
            boom[temp]++;
            boom1[pa[temp]]++;
            boom2[pa[pa[temp]]]++;
            boom3[pa[temp]]++;///对兄弟节点的影响直接记录在父节点上,且这样做还能把自己点上的也算上
            printf("%d\n",boom1[temp]+boom2[temp]+boom[pa[temp]]+boom[pa[pa[temp]]]+boom3[pa[temp]]);
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值