Gym 103117

博主分享了自己在ACM竞赛中遇到的一道关于图论的问题,最初尝试使用邻接矩阵存储图,但因内存问题转而采用邻接表。在理解和实现邻接表的过程中遇到困难,最终通过阅读他人代码解决问题。博主认识到清晰的解题思路的重要性,并计划回头再研究此题。同时,博主对vector容器有了新的认识,并意识到在算法竞赛中学习和运用不同数据结构的必要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

L题 Spicy Restaurant

Problem - L - Codeforces

        累了 已经盯着这个题目 从训练赛看到现在了 写不动了写不动了 先把代码放这 以后再来想吧 自己什么破脑子wwww

        这是第二次组队赛遇到的题目 一开始以为只是常规广搜题 所以跟这题目磕了很久          .

        一开始最大的问题就是不知道该用什么结构来存...自己图这块学的太差了 最后决定用邻接矩阵 所以开了这样一个数组

        bool arcs[100005][100005];

        ......

        然后程序运行不了 我的朋友看了之后跟我说

        还是看一遍笑一遍

        不过在我开这么大数组之前 我的数据好像就出错了 不管了不想再想了 直接换一种再来

        数据结构书上只有邻接表和邻接矩阵两种 既然邻接矩阵不行 那就邻接表吧 写出来还是不对 是哪出了问题呢

        我终于点开了别人的代码

        是的当时就这个表情

        ......不知道该说什么好了 从头懵到尾吧 先放下代码 注释都是我自己写的是我目前的理解 可能会有不对的地方 以后理解了再来修改吧 能理解到的基本都写了 没写的就是还不懂的地方

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;

const int maxn = 100010;
const int inf = 0x3f3f3f3f;//无穷大
int head[maxn+5];//头结点
int nex[maxn*20];//记录该点的下一个结点     至于为什么一定要×20
int ver[maxn*20];//记录结点对应序号             ..... 
int tot;

void add(int u, int v)//增加边
{
    ver[tot] = v;//新建一个结点值为v
    nex[tot] = head[u];//刚建的新节点指向head[x]原先指向的边
    head[u] = tot++;//head[u]再指向当前的结点
}

int ans[maxn*5];//存储答案
int W[maxn];//存储各餐馆辣度
int dis[maxn];//存储距离

void bfs(int n, int v)//n是餐馆总数 v是会从1循环至100的辣度
{
    queue<int> q;//建一个队列
    for (int i = 1; i <= n; i++)//遍历每一个餐馆
    {
        if (W[i] == v)//如果餐馆i的辣度等于当前辣度
        {
            q.push(i);
            dis[i] = 0;
        }
    }
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i = head[u]; ~i; i = nex[i])//~i 的意思是 i!=-1 i一开始是头结点 然后依次往下指 直到i(结点tot)等于-1 因为由add函数可知结点最小为0
        {
            int v = ver[i];//v表示该结点对应的餐馆序号
            if (dis[v] > dis[u] + 1)
            {
                dis[v] = dis[u] + 1;
                q.push(v);
            }
        }
    }
}

vector<pair<int, int> > Q[110];//建了110个容器
int main()
{
    int n, m, q;
    while (scanf("%d%d%d", &n, &m, &q) == 3)
    {
        tot = 0;//节点的下标
        memset(head, -1, sizeof(head));//清空头结点
        for (int i = 1; i <= n; i++)
            cin>>W[i];//输入各餐馆辣度

        while (m--)//建立道路
        {
            int u, v;
            cin>>u>>v;
            add(u, v);
            add(v, u);//因为是无向道路 所以建两条边
        }

        for (int i = 1; i <= 100; i++)
            Q[i].clear();//容器初始化

        for (int i = 0; i < q; i++)
        {
            int p, a;
            scanf("%d%d", &p, &a);//输入游客当前所在位置和最大能承受的辣度
            Q[a].push_back(make_pair(i, p));//尾部插入( i , p ) 第i个游客 所在p位置
        }

        for (int i = 1; i <= n; i++)
            dis[i] = inf;//初始化dis为正无穷

        for (int v = 1; v <= 100; v++)//对每一个辣度进行遍历
        {
            bfs(n, v);
            for (int i = 0; i < Q[v].size() ; i++)
            {
                int id = Q[v][i].first;//第几个游客
                int u = Q[v][i].second;//游客当前所在位置
                if (dis[u] == inf)//如果没有找到符合条件的辣度
                    ans[id] = -1;
                else
                    ans[id] = dis[u];
            }
        }
        for (int i = 0; i < q; i++)
            printf("%d\n", ans[i]);
    }
    return 0;
}

        在add函数上就耗了很久的时间 一直不懂这到底是用什么来存的 后来我发现原来这就是邻接表啊救命。。。这才慢慢理解add函数的意思

        这次还接触到了vector容器 之前在书上看到过但没仔细看 但是感觉好奇妙 就结果来看 运行时间和内存都相对来说不是那么大 是可以值得专门学一下并且加以利用的知识点

         我觉得从训练赛开始到现在一直都没能理解的原因大概还是对于这道题目没有清晰的思路吧 不知道它整体是想干嘛 好像知道一点又好像不知道 只能分部理解一部分 所以心情一直反反复复的烦躁

        等过段时间我一定回来再好好看 这题再看下去我又要觉得自己不适合acm了

        后来才知道 原来差不多类型的题目就在前一天晚上打acwing周赛的时候就刚好遇到了 只是自己写完两题就比赛结束了 后来也没有勇气去补第三题 要是能逼自己去看一下就好了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值