萌新刚学OI 1m37s,最短路求调QwQ!
  • 板块CF59E Shortest Path
  • 楼主Moyou
  • 当前回复0
  • 已保存回复0
  • 发布时间2022/11/27 17:31
  • 上次更新2023/10/27 01:11:43
查看原帖
萌新刚学OI 1m37s,最短路求调QwQ!
597798
Moyou楼主2022/11/27 17:31

思路:

将一条无向边 (i, j) 拆分成两个有向边,每个有向边转换为一个点,给一个编号,用 dist[ei] 表示从 1号点到边 eie_i 的最短路径长度,这样方便我们转移。

接着由于边权为1,直接bfs,每次扩展的时候都判断一下要扩展的点可不可以从 eie_i 转移过去,这个可以预处理出来,最后记录前驱,递归输出。

至于无解判断,当所有到达n的点距离都为INF时即无解。

可是这个代码在 Test7 WA了,原因是无解判断错了,本来是有解的,大佬们求求调一调8 qwq!

// Problem: Shortest Path
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF59E
// Memory Limit: 250 MB
// Time Limit: 3000 ms
// Author: Moyou
// Copyright (c) 2022 Moyou All rights reserved.
// Date: 2022-11-27 15:39:41

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#define x first
#define y second
#define INF 0x7f7f7f7f
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;

const int N = 3000 + 10, M = 20010, K = 1e5 + 10;

int h[N], ne[M], e[M], idx;
int dist[M];
void add(int a, int b)
{
    e[++idx] = b, ne[idx] = h[a], h[a] = idx;
}

struct trip
{
    int a, b, c;
    bool operator<(const trip &T) const
    {
        if (a != T.a)
            return a < T.a;
        else
            return b < T.b;
    }
} dis[K];

vector<int> forbid[M]; // 记录对于每一个边不可行的点
map<PII, int> es; // 点对对应的边编号
map<int, PII> ep; // 边编号对应的点对
bool mark[N]; // 每次扩展的时候计算,mark[i]表示当前边是否能扩展到i点
bool st[M]; // bfs
int n, m, k;
int pred[M]; // 前驱

int bfs(int s)
{
    memset(dist, 0x7f, sizeof dist);
    queue<PII> q;
    for (int i = h[s]; ~i; i = ne[i])
    {
        int j = e[i];
        q.push({s, j});
        dist[es[{s, j}]] = 1;
    }
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        
        int edge = es[{t.x, t.y}];
        
        if(t.y == n && dist[es[{t.x, t.y}]] != INF) return t.x;
        if(st[edge]) continue;
        st[edge] = 1;
        
        for (int i = 1; i <= n; i++)
            mark[i] = 1;
        for (auto i : forbid[edge])
            mark[i] = 0;
        for (int i = h[t.y]; ~i; i = ne[i])
        {
            int j = e[i], e2 = es[{t.y, j}];
            if (!mark[j])
                continue;
            dist[e2] = dist[edge] + 1;
            if(!pred[e2])pred[e2] = edge; 
            q.push({t.y, j});
        }
    }
    return -1;
}
int cnt;
vector<int> out;
void write(int p)
{
	if(ep[p].x == 1)
	{
		cnt ++;
		out.push_back(ep[p].y);
		// cout << ep[p].y << ' ';
		return ;
	}
	// cout << p << ' ' << ep[p].x << ' ' << ep[p].y << endl;
	cnt ++;
	write(pred[p]);
	out.push_back(ep[p].y);
	// cout << ep[p].y << ' ';
}

int main()
{
    memset(h, -1, sizeof h);
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);
        es[{a, b}] = 2 * (i - 1) + 1;
        es[{b, a}] = 2 * (i - 1) + 2;
        ep[2 * (i - 1) + 1] = {a, b};
        ep[2 * (i - 1) + 2] = {b, a}; // 设置编号
    }

    for (int i = 1; i <= k; i++)
        cin >> dis[i].a >> dis[i].b >> dis[i].c;
    sort(dis + 1, dis + k + 1);
    for (int i = 1; i <= k; i++)
    {
        forbid[es[{dis[i].a, dis[i].b}]].push_back(dis[i].c);
    }
    int ans = bfs(1);
    if (ans == -1)
    {
        puts("-1");
        return 0;
    }
    out.push_back(1);
    write(es[{ans, n}]);
    cout << cnt << endl;
    for(auto i : out) cout << i << ' ';
    return 0;
}

欧内该!qwq

2022/11/27 17:31
加载中...