虫洞问题(最短路)

在探索他的许多农场时,农夫约翰发现了许多惊人的虫洞。虫洞非常奇特,因为它是一条单行道,在你进入虫洞之前的时间将你送到目的地!FJ的每个农场都包括N(1≤N≤500)田地,编号为1。NM(1 ≤ M ≤ 2500)路径和W(1 ≤ W ≤200)虫洞。

由于FJ是一个狂热的时间旅行爱好者,他想做以下事情:从某个场地开始,穿过一些路径和虫洞,并在他最初离开之前的时间返回起跑场。也许他能够:)见到自己。

为了帮助FJ了解这是否可能,他将为您提供其农场F(1 ≤ F ≤ 5)的完整地图。任何路径都不会花费超过10,000秒的时间来行驶,也没有虫洞可以将FJ带回超过10,000秒的时间。

ac代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#define MAXN 100010
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m, w;
int head[MAXN], ed[MAXN], val[MAXN], nex[MAXN], idx;
int dist[MAXN], vis[MAXN], cnt[MAXN];
void add(int x, int y, int z) {//链式前向星储路径
    ed[idx] = y;
    val[idx] = z;
    nex[idx] = head[x];
    head[x] = idx++;
}
int spfa()
{
    int i;
    memset(dist, 0x3f, sizeof(dist));//初始化距离为无穷大
    memset(vis, 0, sizeof(vis));//队列中标记为1,不在队列中为0
    memset(cnt, 0, sizeof(cnt));//表示当前点到起点最短路的边数,初始化为0个;
    queue<int> q;//队列
    for (i = 1; i <= n; i++)
    {
        vis[i] = 1;//准备放入队列,标记
        q.push(i);//把所有点作为初始点塞进队列
    }
    while (q.size() > 0) {//几乎就是spfa算法了。
        int temp = q.front();
        q.pop();
        vis[temp] = 0;
        for (int i = head[temp]; i != -1; i = nex[i]) {
            if (dist[ed[i]] > dist[temp] + val[i]) {
                dist[ed[i]] = dist[temp] + val[i];
                cnt[ed[i]] = cnt[temp] + 1;
                if (cnt[ed[i]] >= n)
                    return 1;
                if (vis[ed[i]] == 0) {
                    q.push(ed[i]);
                    vis[ed[i]] = 1;
                }
            }
        }
    }
    return 0;
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--)
    {
        memset(head, -1, sizeof(head));
        scanf("%d %d %d", &n, &m, &w);
        for (int i = 1; i <= m; i++) {
            int x, y, z;
            scanf("%d %d %d", &x, &y, &z);
            add(x, y, z);
            add(y, x, z);//双向
        }
        for (int i = 1; i <= w; i++)
        {
            int x, y, z;
            scanf("%d %d %d", &x, &y, &z);
            add(x, y, -z);//虫洞是回溯时间,z为-的;
        }
        int res = spfa();
        if (res == 1)
            printf("YES\n");//有一次还把大小写看错了,啊这
        else printf("NO\n");
    }
    return 0;
}

 这里呢,我再展示下我的超时代码,ac代码思路是受大佬启发的,下面代码是我最初的想法。

#include<iostream>//超时代码
#include<cstring>
#include<algorithm>
#include<queue>

#define MAXN 100010

using namespace std;

const int inf = 0x3f3f3f3f;
int n, m,w;
int head[MAXN], ed[MAXN], val[MAXN], nex[MAXN], idx;
int dist[MAXN], vis[MAXN], cnt[MAXN];

void add(int x, int y, int z) {
    ed[idx] = y;
    val[idx] = z;
    nex[idx] = head[x];
    head[x] = idx++;
}

int spfa() {
    int i;
    for (i = 1; i <= n; i++)、、(是我心存侥幸了)
    {
        int start = i;
        memset(dist, 0x3f, sizeof(dist));
        memset(vis, 0, sizeof(vis));
        memset(cnt, 0, sizeof(cnt));
        dist[start] = 0;
        vis[start] = 1;
        queue<int> q;
        q.push(start);
        while (q.size() > 0) {
            int temp = q.front();
            q.pop();
            vis[temp] = 0;
            for (int i = head[temp]; i != -1; i = nex[i]) {
                if (dist[ed[i]] > dist[temp] + val[i]) {
                    dist[ed[i]] = dist[temp] + val[i];
                    cnt[ed[i]] = cnt[temp] + 1;
                    if (cnt[ed[i]] >= n)
                        return 1;
                    if (vis[ed[i]] == 0) {
                        q.push(ed[i]);
                        vis[ed[i]] = 1;
                    }
                }
            }
        }
    }
    return 0;
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--)
    {
        memset(head, -1, sizeof(head));
        scanf("%d %d %d", &n, &m, &w); 
        for (int i = 1; i <= m; i++) {
            int x, y, z;
            scanf("%d %d %d", &x, &y, &z);
            add(x, y, z);
            add(y, x, z);
        }
        for (int i = 1; i <= w; i++)
        {
            int x, y, z;
            scanf("%d %d %d", &x, &y, &z);
            add(x, y, -z);
        }
        int res = spfa();
        if (res == 1)
            printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
bugstack栈是一个以技术为核心的社群和知识分享平台。在这个平台上,程序员、软件开发者和技术爱好者可以交流、学习和分享各种与技术相关的话题和经验。 首先,bugstack栈提供了丰富多样的技术资源。在这个平台上,用户可以找到各种编程语言、开发框架和技术工具的教程、文档和案例。这些资源涵盖了从初级到高级的各个层次,无论你是刚入门的新手还是资深的专家,都可以在这里找到适合自己的学习材料。 其次,bugstack栈注重用户之间的交流和互动。用户可以在平台上发表自己的观点、经验和问题,与其他人进行讨论和互动。这种交流不仅可以加深自己对技术的理解和掌握,还可以结交到更多志同道合的朋友和同行,激发创新思维和解决问题的能力。 此外,bugstack栈还举办各种线上线下的技术活动。比如技术讲座、技术沙龙、技术峰会等。这些活动不仅给用户提供了进一步学习和分享的机会,还可以拓宽用户的视野,了解更多前沿的技术和行业趋势。 总之,bugstack栈是一个面向技术爱好者的社群平台,它提供了丰富多样的技术资源,注重用户之间的交流和互动,举办各种技术活动,为用户提供一个学习、交流和成长的平台。无论你是想学习新技术、解决问题,还是寻找合作伙伴或者拓展人脉,这个平台都是一个理想的选择。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值