[POI2013]MOR-Tales of seafaring 洛谷3556 bfs

66 篇文章 0 订阅

Description


Young Bytensson loves to hang out in the port tavern, where he often listens to the sea dogs telling their tales of seafaring.

Initially, he believed them all, however incredible they sounded.

Over time though, he became suspicious.

He has decided to write a program that will verify if there may be any grain of truth in those tall stories.

Bytensson reasoned that while he cannot tell if the sailors indeed weathered all those storms, he can at least find out if their travel itineraries make sense.

This is a task for a programmer, which Bytensson, unfortunately, is not.

Help him out!

There are ports and waterways connecting them in the waters frequented by the sailors Bytensson listened to.

If there is a waterway between two ports, then sailing from one to the other is possible. Any waterway can be sailed in both directions.

Bytensson got to know seafaring tales.

Each tells of a sailor who began his journey in one port, sailed a number of waterways, and ended up in another port, which may have been the one he initially set sail from.

The sailor in question may have sailed through the same waterway many times, each time in any direction.

给n个点m条边无向图,每次询问两个点之间是否有长度为d的路径(不一定是简单路径)

Solution


这道题是很神奇的

首先不一定是简单路径,那么只要奇偶性相同就行了,那么分别记录两点间奇数步的最短路和偶数步的最短路,输出的时候判断一下就行了。考虑到洛谷神奇的内存限制和数据范围,这里用short是可以存下的。

特殊地,只有一个点的时候无论奇偶都是不能到达本身的

神奇的洛谷姬跑T了1个点,求指导各种玄学优化

请忽略那个名为spfa实际是bfs的函数名

Code


#include <stdio.h>
#include <string.h>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x))
#define N 5001
#define E N * 3 + 1
struct edge{int x, y, next;}e[E];
inline int read(){
    char ch = getchar(); int x = 0;
    while (ch < '0' || ch > '9'){
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0'){
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    return x;
}
short ls[N];
inline int addEdge(int &cnt, int x, int y){
    cnt += 1; e[cnt] = (edge){x, y, ls[x]}; ls[x] = cnt;
    cnt += 1; e[cnt] = (edge){y, x, ls[y]}; ls[y] = cnt;
}
short dis[N][N][2], que[N + 1];
bool inQueue[N][2], cal[N];
inline void spfa(int st, int n){
//    fill(inQueue, 0);
    rep(i, 0, n){
        dis[st][i][0] = -1;
        dis[st][i][1] = -1;
    }
    inQueue[st][0] = 0;
    dis[st][st][0] = 0;
    int head = 0, tail = 2;
    que[1] = st;
    que[2] = 0;
    while (head != tail){
        head = head % N + 1;
        int now = que[head];
        head = head % N + 1;
        int stp = que[head];
        erg(i, now){
            if (dis[st][e[i].y][stp ^ 1] == -1){
                dis[st][e[i].y][stp ^ 1] = dis[st][now][stp] + 1;
                cal[st] = 1;
                if (!inQueue[e[i].y][stp ^ 1]){
                    inQueue[e[i].y][stp ^ 1] = 1;
                    tail = tail % N + 1;
                    que[tail] = e[i].y;
                    tail = tail % N + 1;
                    que[tail] = stp ^ 1;
                }
            }
        }
        inQueue[now][stp] = 0;
    }
}
int main(void){
    int n = read(), m = read(), k = read();
    int edgeCnt = 0;
    rep(i, 1, m){
        int x = read(), y = read();
        addEdge(edgeCnt, x, y);
    }
    rep(i, 1, n){
        spfa(i, n);
    }
    while (k --){
        int x = read(), y = read(), d = read();
        if ((dis[x][y][d & 1] == -1) || (x == y && d > 0 && !cal[x]) || (dis[x][y][d & 1] > d)){
            puts("NIE");
        }else{
            puts("TAK");
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值