SDUT 2622 - 最短路径(SPFA+二维)

题目链接


http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/2622.html

题目大意


有一个有向图,给定一个终点和起点,求起点到终点的最短路径,并且路径经过的边数是 x 的倍数。

解题过程


想了好长时间,最初是想把每次的步数一起装到队列里面,用 SPFA 。
然后 WA , 只好去搜了下博客,原来是多了个维度,和之前做的一个题神似,UVA1600 ,这个是多了一个维度的BFS,以后得想起来这个加一个维度解决问题的方法了,要不遇到就卡死。

题目分析


  • 大体思路是用 SPFA ,增加一个维度,储存步数对 x 取模,最后输出对 x 取模后是 0 的终点距离即可。

AC代码


#include<bits/stdc++.h>
using namespace std;

struct node
{
    int v;
    long long w;
    node(int v, long long w):v(v),w(w){}
};

vector<node> edges[112];
bool book[112];
long long dis[112][11];
int s, e, x;
int n, m;

int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d %d", &n, &m);
        memset(book, 0, sizeof(book));
        memset(dis, -1, sizeof(dis));
        for (int i = 0; i < n; i++)
            edges[i].clear();

        for (int i = 0; i < m; i++)
        {
            int u, v;
            long long w;
            scanf("%d %d %lld", &u, &v, &w);
            edges[u].push_back(node(v,w));
        }

        scanf("%d %d %d", &s, &e, &x);
        queue<int> q;
        q.push(s);
        dis[s][0] = 0;

        while (!q.empty())
        {
            int u = q.front();

            for (int i = 0; i < edges[u].size(); i++)
            {
                int v = edges[u][i].v;
                long long w = edges[u][i].w;
                for (int k = 0; k < x; k++)
                {
                    if (dis[u][k] != -1 && (dis[v][(k+1)%x] > dis[u][k] + w || dis[v][(k+1)%x] == -1))
                    {
                        dis[v][(k+1)%x] = dis[u][k] + w;
                        if (!book[v])
                        {
                            q.push(v);
                            book[v] = 1;
                        }
                    }
                }
            }
            book[u] = 0;
            q.pop();
        }

        if (dis[e][0] == -1)
            printf("No Answer!\n");
        else
            printf("%lld\n", dis[e][0]);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值