HDU 3760 Ideal Path 最短路+BFS

这题的话其实想是比较好像的,就是写起来代码比较多

题目大意就是给出了一个无向图,每条边有一个编号。

然后让我们求一条编号字典序最小的最短路

那么首先我们做两遍SPFA,分别求出起点到所有点的距离,以及终点到所有点的距离

这样我们就能判断某个点是否是最短路上的点

之后我们进行BFS ,其实刚才求最短路BFS也行,因为每条边的权值都是1.

然后BFS是这样的,假设我们已经BFS了x层了,然后起所有x层的点能到的点能并且是最短路上的点记为第x+1层的点,然后就找出这些边中的最小编号,也就是第x+1步要输出的答案。

然后把第x+1层的点中编号是最小编号的点加入到队列里。

记得要标记。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#define MAXN 100005
#define MAXM 400005
#define INF 1000000011
#define lch(x) x<<1
#define rch(x) x<<1|1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define eps 1e-7
using namespace std;
struct EDGE
{
    int v, w, next;
}edge[MAXM * 2];
int head[MAXN], e;
int dis[2][MAXN];
int vis[MAXN];
void init()
{
    memset(head, -1, sizeof(head));
    e = 0;
}
void add(int u, int v, int w)
{
    edge[e].v = v;
    edge[e].w = w;
    edge[e].next = head[u];
    head[u] = e++;
}
int n, m;
int q[4 * MAXM];
int L;
int color[MAXN];
void spfa(int src, int k)
{
    for(int i = 1; i <= n; i++) dis[k][i] = INF, vis[i] = 0;
    int h = 0, t = 0;
    q[t++] = src;
    dis[k][src] = 0;
    vis[src] = 1;
    while(h < t)
    {
        int u = q[h++];
        vis[u] = 0;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].v;
            if(dis[k][u] + 1 < dis[k][v])
            {
                dis[k][v] = dis[k][u] + 1;
                if(!vis[v])
                {
                    q[t++] = v;
                    vis[v] = 1;
                }
            }
        }
    }
    if(k == 0) L = dis[k][n];
}
struct node
{
    int num, u;
    node(){}
    node(int a, int b){num = a; u = b;}
}que[4 * MAXM];
int pre[MAXN], prec[MAXN];
int ans[MAXN];
void bfs()
{
    int h = 0, t = 0;
    for(int i = 1; i <= n; i++) color[i] = INF, vis[i] = 0;
    vis[1] = 1;
    que[t++] = node(0, 1);
    while(h < t)
    {
        node tmp = que[h];
        if(que[h].num == L) break;
        for(int j = h; j < t; j++)
        {
            if(que[j].num != tmp.num) break;
            int u = que[j].u;
            for(int i = head[u]; i != -1; i = edge[i].next)
            {
                int v = edge[i].v;
                int w = edge[i].w;
                if(dis[0][u] + 1 + dis[1][v] == L)
                {
                    if(w < color[tmp.num + 1]) color[tmp.num + 1] = w;
                }
            }
        }
        while(h < t && que[h].num == tmp.num)
        {
            int u = que[h].u;
            for(int i = head[u]; i != -1; i = edge[i].next)
            {
                int v = edge[i].v;
                if(dis[0][u] + 1 + dis[1][v] == L && color[tmp.num + 1] == edge[i].w && !vis[v])
                {
                    vis[v] = 1;
                    pre[v] = u;
                    prec[v] = edge[i].w;
                    que[t++] = node(tmp.num + 1, v);
                }
            }
            h++;
        }
    }
    int now = n;
    int cnt = 0;
    while(pre[now] != 1)
    {
        ans[cnt++] = prec[now];
        now = pre[now];
    }
    ans[cnt++] = prec[now];
    printf("%d", ans[cnt - 1]);
    for(int i = cnt - 2; i >= 0; i--) printf(" %d", ans[i]);
    printf("\n");
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int x, y, z;
        scanf("%d%d", &n, &m);
        init();
        while(m--)
        {
            scanf("%d%d%d", &x, &y, &z);
            if(x == y) continue;
            add(x, y, z);
            add(y, x, z);
        }
        spfa(1, 0); spfa(n, 1);
        printf("%d\n", L);
        bfs();
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值