CF 20C Dijkstra?

題目鏈接

題意:
給你以後n個點(編號爲1~n),m個無向邊,有可能形成環,問你從 1 到 n 的最短距離是多少,如果到不了就輸出-1, ps:兩點之間可能有多條邊。

思路:
一看這題不是bfs秒了嗎,直接bfs維護每個點的最短距離,

在這裏插入圖片描述
那麼問題來了,爲什麼會T, 點的範圍1e5,邊的範圍1e5, 1e5+1e5沒理由t啊,因爲這不是到了這個點就可以把這個點去掉的bfs,而是要維護到這個點最短距離的bfs,所以每個點很有可能不止經過一次,導致複雜度並不是O(n+m),所以我的解決方法是把輸入的邊先存起來,按照w的值從小到大排序,然後加邊的時候如果a,b兩點已經有變了(我搞了個set), 就跳過,否則就加。
在這裏插入圖片描述

這種輸入邊先排個序在加邊或者遍歷的這種套路還是挺常見的。記得之前div2也有一道用雙bfs做的題,給你一個圖,允許你加一條邊,問你兩個點之間的最短距離是多少(此題在這), 利用式子移項以後都變成同一個下標的關係,可以sort,遍歷一遍解決。

#include <bits/stdc++.h>

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, a, b) for (int i = (int)(a); i >= (int)b; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define ms(x, y) memset(x, y, sizeof(x))
#define SZ(x) ((int)(x).size())

using namespace std;

typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpi;
typedef vector<vi> vvi;
typedef long long i64;
typedef vector<i64> vi64;
typedef vector<vi64> vvi64;
typedef pair<i64, i64> pi64;
typedef double ld;

template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }

const i64 maxn = (int)1e5+1000;
i64 n, m, pref[maxn], dist[maxn];
struct node {
	int a, b, w;
}input[maxn];
vector< vector< pair<i64, i64> > > g(maxn);
set<int> st[maxn];

void bfs() {
	queue< i64 > q;
	i64 cur, nxt;
	dist[1] = 0;
	q.push(1);
	while (!q.empty()) {
		cur = q.front();
		q.pop();
		for (pii to : g[cur]) {
			if (dist[to.fi] > dist[cur]+to.se) {
				dist[to.fi] = dist[cur]+to.se;
				pref[to.fi] = cur;
				q.push(to.fi);
			}
		}	
	}
}

int main() {
	ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.precision(10);
    cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
	
	cin >> n >> m;
	forn(i, m) cin >> input[i].a >> input[i].b >> input[i].w;
	sort(input, input+m, [&](node n1, node n2) {
		return n1.w<n2.w;
		});
	forn(i, m) {
		if (st[input[i].a].find(input[i].b) == st[input[i].a].end()) {
			st[input[i].a].insert(input[i].b);
			st[input[i].b].insert(input[i].a);
     		g[input[i].a].pb({input[i].b, input[i].w});
     		g[input[i].b].pb({input[i].a, input[i].w});
		}
	}
	for1(i, n) dist[i] = LLONG_MAX;
	ms(pref, -1);
	bfs();
	if (dist[n] == LLONG_MAX) cout << -1 << '\n';
	else {
		vi ans;
		i64 temp = n;
		while (temp != -1) {
			ans.eb(temp);
			temp = pref[temp];
		}
		reverse(all(ans));
		for (i64 x : ans) cout << x << ' ';
		cout << '\n';
	}
	            
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章