PAT_1021 Deepest Root (25 分) (记录段错误和超时的解决)

题目链接
在这里插入图片描述
在这里插入图片描述

首先跑一遍DFS获取连通分支数,当只有一个连通分支时,再搜索能让树最深的根节点(主要参考《算法笔记》的做法)。

记录一下错误:

  1. 段错误:基本上段错误都是因为数组越界导致的,要么是数组开的不够大,要么访问了数组外的地址,本题中告诉N个结点,接下来N-1行是边的信息,如果for循环写顺手很容易写成i=0;i<N;i++,应该是i=0;i<N-1;i++,当然这还是审题不清的锅。
  2. 按照《算法笔记》讲的思想,首先从任意节点出发dfs得到一个最深的叶结点集合A,然后从A集合中任意选一个结点出发dfs得到另一个最深的叶结点集合B,A和B的并集就是最终结果(使用set可以避免排序和去重)。一开始写成了对A集合中的每一个结点都进行了一次dfs,导致测试点3超时。

代码:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
vector<int> G[10005];
int vis[10005]={0};
set<int> ans;
set<int> tmp;//随便选一个结点开始深搜得到的最深的顶点
int maxdeep=-1;//记录深度
void dfs(int v,int deep){//pre防止访问回来
    vis[v]=1;
    for(auto w:G[v]){
        if(!vis[w]){
            dfs(w,deep+1);
        }
    }
    if(deep>maxdeep){
        maxdeep=deep;
        tmp.clear();
        tmp.insert(v);
    }else if(deep==maxdeep){
        tmp.insert(v);
    }
}
void dfscon(int v){
    vis[v]=1;
    for(auto w:G[v]){
        if(!vis[w]){
            dfscon(w);
        }
    }
}
int main() {
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt","r",stdin);
#endif

    int N;
    cin >> N;
    for(int i=0;i<N-1;i++){//N-1行啊!!!! 段错误!!
        int v,w;
        cin >> v >> w;
        G[v].push_back(w);
        G[w].push_back(v);
    }
    //先求连通分支数,若大于2都不需要接着搜了
    int k=0;
    for(int i=1;i<=N;i++){
        if(!vis[i]){
            k++;
            dfscon(i);
        }
    }
    if(k>1) cout << "Error: "<< k << " components";
    else{
        memset(vis,0,sizeof(vis));
        dfs(1,0);//先dfs出一个临时最深的集合
        for(set<int>::iterator it=tmp.begin();it!=tmp.end();it++){//将这个集合先放到ans中
            ans.insert(*it);
        }

        memset(vis,0,sizeof(vis));
        dfs(*ans.begin(),0);

        for(set<int>::iterator it=tmp.begin();it!=tmp.end();it++){//再最后合并
            ans.insert(*it);
        }
        for(set<int>::iterator it=ans.begin();it!=ans.end();it++)
            cout << *it << endl;
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值