欢迎来到lbxer的博客
lbxer
lbxer
晓看天色暮看云,行也思君,坐也思君

csp赛前刷题 搜索篇 Tales of seafaring

https://www.luogu.com.cn/problem/P3556

题意分析

注意题目中的 “(不一定是简单路径)”,也就是说可以在一条边重复走多次,也就是可以在两个点之间反复横跳

反复横跳意味着什么,如果从 ss (起点)走到 tt (终点)如果没有 dd 那么长,比 dd 要短,可以在最后两个点不断来回重复走,使路径 =d=d ,但是要注意一点,反复横跳每次都会把路径长度 +2+2。

所以 ss 走到 tt 的路径必须是和 dd 奇偶性相同,我们只需要求出 ss 到 tt 的奇数最短路径和偶数最短路径即可。

那么怎么找呢?我们又发现它的边权全都是1,所以我们用奇数最短路来更新偶数最短路,用偶数最短路来更新奇数最短路。另外,因为有很多询问的起点都是一样的,所以我们珂以离线来做。

然而还并没有结束。就像下面这组数据:

1 0 1
1 1 2

应该输出NIE,但我们会发现我们的程序输出的是TAK,为什么呢?因为我们对1号节点赋的初值为0,但我们在后面并没有更新它,所以我们应该记录一下我们队列里进了几个元素,倘若只进了一个元素,就说明这是一个孤立的点,那就是不存在了。

还要注意此题为无向图

🆗 上代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
int n, m, x, y, z, k, s, t, tot, las;
const int N = 1000100, inf = 999999999;
int head[N], fa[N], dis1[N], dis2[N];
bool vis[N], ans[N];
struct bian
{
    int to, nt;
}e[N];
struct ask
{
    int s, t, lu, id;
    friend bool operator <(const ask& a, const ask& b)
    {
        return a.s < b.s;
    }
}Q[1000100];
void add(int f, int t)
{
    e[++tot].to = t;
    e[tot].nt = head[f];
    head[f] = tot;
}
int find(int x) { return x == fa[x] ? fa[x] : fa[x] = find(fa[x]); }
void he(int x, int y) { fa[find(x)] = fa[find(y)]; }
queue<int>q;
void spfa(int s)
{
    int x, in = 0;
    for (int i = 1; i <= n; ++i)dis1[i] = dis2[i] = inf;
    dis2[s] = 0; q.push(s); vis[s] = 1;
    while (!q.empty())
    {
        x = q.front(); q.pop(); vis[x] = 0; in++;
        for (int i = head[x]; i; i = e[i].nt)
        {
            if (dis2[e[i].to] > dis1[x] + 1)
            {
                dis2[e[i].to] = dis1[x] + 1;
                if (!vis[e[i].to])
                {
                    q.push(e[i].to);
                    vis[e[i].to] = 1;
                }
            }

            if (dis1[e[i].to] > dis2[x] + 1)
            {
                dis1[e[i].to] = dis2[x] + 1;
                if (!vis[e[i].to])
                {
                    q.push(e[i].to);
                    vis[e[i].to] = 1;
                }
            }
        }
    }
    if (in == 1)dis1[s] = dis2[s] = inf;
    for (int i = las; Q[i].s == Q[las].s; ++i)
    {
        if (Q[i].lu & 1)ans[Q[i].id] = (dis1[Q[i].t] <= Q[i].lu);
        else ans[Q[i].id] = (dis2[Q[i].t] <= Q[i].lu);
    }
}
int main()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= n; ++i)fa[i] = i;
    for (int i = 1; i <= m; ++i)
    {
        cin>>x>>y;
        he(x, y);
        add(x, y); add(y, x);
    }
    for (int i = 1; i <= k; ++i)
    {
        cin>>Q[i].s>>Q[i].t>>Q[i].lu;
        Q[i].id = i;
        if (Q[i].s > Q[i].t)swap(Q[i].s, Q[i].t);
    }
    sort(Q + 1, Q + 1 + k);
    for (int i = 1; i <= k; ++i)
    {
        while (Q[i].s == Q[las].s)++i;
        las = i; spfa(Q[i].s);
    }
    for (int i = 1; i <= k; ++i)
    {
        if (ans[i])cout << "TAK" << endl;
        else cout<<"NIE"<<endl;
    }
    fclose(stdin); fclose(stdout);
    return 0;
}
View Code

 

posted @ 2020-10-09 15:24  雷痕小祥  阅读(143)  评论(0编辑  收藏  举报
Live2D