PAT甲级 1034

文章描述了一段C++代码,该代码用于寻找图的连通分量并计算其权值。作者指出了在实现深度优先搜索(DFS)过程中遇到的一些问题,如忘记初始化变量、参数传递错误、使用哈希表存储图边等。修复这些问题后,代码能够正确找到满足特定条件的帮派(权值大于k且成员数大于2),并按字典序输出结果。
摘要由CSDN通过智能技术生成

犯的错

整体思路没有提前写好 导致写代码的时候经常丢东西 
需要写一个备忘录 记录一下例如 sum 最后需要除2的事情 避免遗忘
关注函数传参(尤其在递归的时候) 定义了2个参数 不能只传回去一个参数
出错了 一个vector里面要有两个东西 需要用pair
出错了 vector 不是一个结构体 里面的东西需要push

代码

/*
    分析:我们要找连通图    连通图可以用BFS DFS 用 DFS可以少写一个队列 因此用DFS 在用DFS的时候 我们需要统计 1.多少个点 2.多少个边
    输入是文字 会想到用hash表来存储 需要映射 hash表存在unordered_map里面
    最后是字典序 需要用到sort 需要algorithm
*/

#include <iostream>
#include <unordered_map>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

int n, k;
//有图 需要存领接矩阵 用一张哈希表来存读取的领接矩阵 当前节点是谁 到哪个节点 边权是多少
unordered_map<string, vector<pair<string, int>>> edge;
//存一下 每个节点的值是多少
unordered_map<string, int> value;
//为了使用dfs 每个点是否被访问过 索引是字符串 所以用hash表存
unordered_map<string, bool> st;

//构造DFS 使用递归 返回帮派权值和
int dfs(string ver, vector<string> &nodes)
{
    // 忘记定义sum了
    int sum  = 0;
    //进入dfs就标记我访问过了
    st[ver] = true;
    //遗漏:把当前节点加入当前连通图 nodes
    nodes.push_back(ver); 
    //DFS 递归搜索这个图 遍历当前节点所连接的边(通过访问这个边的领接矩阵)
    //打开当前节点 需要更新的有 1.sum
    //如果这个边对应的节点 已经被访问过就跳过 如果没有被访问过则对这个节点使用DFS
    for (auto e : edge[ver])//犯错了:不应该打开的是所有的edge 应该打开的是单独的,有 vertex 连接的 edge 所以应该改成 edge[ver]
    {//从领接矩阵里面拿出来所有的边
        sum += e.second;
        if (!st[e.first])
        {
            sum += dfs(e.first, nodes);
            //犯错了 sum不是全局变量所以要依靠dfs的返回值来传递递归中的sum值
            //犯错了 dfs要传入了两个参数我只传入了一个
        }
    }
    return sum;
}

int main()
{
    cin >> n >> k;
    while (n -- )
    {//读入信息
        string a, b;
        int t;//存放边权
        cin >> a >> b >> t;
        //放入领接矩阵 另一种方式考虑bfs 我把每条边算两次最后除以2就可以
        edge[a].push_back({b, t});
        edge[b].push_back({a, t});
        //更新当前点的点权
        value[a] += t;
        value[b] += t;
    }
    //把图建完之后 要dfs找连通图 找到连通图的时候 边找边把权值加起来 要知道有多少个节点(需要开一个新的空间用于储存连通图的节点,并)
    //建立最后输出的res res由成对的名字和帮派成员数量构成 记为res
    vector<pair<string, int>> res;
        //做DFS搜每一个节点的连通图 因为是hash表 所以 遍历每个vertex会自己去重 通过value遍历每个节点
    for (auto ver : value)
    {//ver 代表 vertex
        string ver_name = ver.first;
        //使用dfs找连通图 得到连通图的权值和
        //需要传入存放一个帮派节点的空间
        vector<string> nodes;
        // 犯错了 sum要除以2 忘记除了
        int sum = dfs (ver_name, nodes) / 2;
        // 判断当前帮派是否合法 需要通过 1.权值大小(sum) 2.帮派人员数(nodes.size())
        if(sum > k && nodes.size() > 2)
        {// 帮派存在的话
            // 找到老大是谁
            // 遍历nodes中的每一个节点 如果当前节点的值比记录的最大值要大的话 那就更新boss的值 新建一个变量boss 
            // 出错了 一个vector里面要有两个东西 需要用pair
            // 出错了 vector 不是一个结构体 里面的东西需要push
            
            string boss = nodes[0];
            int boss_value = value[boss];
            for(auto inode : nodes)
            {
                if (value[inode] > boss_value)
                {
                    boss = inode;
                    boss_value = value[inode];
                }
            }
            //更新res
            res.push_back({boss, nodes.size()});
        }
    }
    // 字典序输出 需要使用sort
    sort(res.begin(), res.end());
    // 输出帮派数量
    cout << res.size() << endl;
    for (auto i : res)
    {
        cout << i.first << ' ' << i.second << endl; 
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值