本文主要是介绍[USACO23FEB] Moo Route II S 题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
比较有意思。
无法保证每个点只被访问一遍,而此题每条边显然不会重复走,考虑保证每条边仅走一次。
一种 naive 的想法就是标记边是否走过。举个例子:
for(int i=1; i<=n; i++)if(vis[i]) continue;
仍然是 O ( n ) 。 O(n)。 O(n)。
然后就考虑每次只访问有必要的边。对 u u u 出边按 r r r 排序,二分找出当前时间下还有必要访问的边。排序后访问到一条走过的边,显然就不用继续遍历接下来的出边了。
#include<bits/stdc++.h>
#define int long long
using namespace std;const int N = 2e5 + 5;struct Edge{int c, r, d, s;bool vis;
};int n, m, a[N], dis[N];vector <Edge> G[N];void dfs(int u, int T)
{int l = 0, r = G[u].size() - 1, mid, pos = 1e9;while(l <= r){mid = l + r >> 1;if(G[u][mid].r >= T) pos = mid, r = mid - 1;else l = mid + 1;}for(int i = pos; i < G[u].size(); i ++ ){if(G[u][i].vis) return;G[u][i].vis = 1;int to = G[u][i].d;if(G[u][i].s < dis[to]) dis[to] = G[u][i].s, dfs(to, G[u][i].s + a[to]);}
}signed main()
{ios::sync_with_stdio(0); cin.tie(0);cin >> n >> m;for(int i=1; i<=m; i++){Edge x; x.vis = 0;cin >> x.c >> x.r >> x.d >> x.s;G[x.c].push_back(x);}for(int i=1; i<=n; i++)cin >> a[i], dis[i] = 1e9;for(int i=1; i<=n; i++) sort(G[i].begin(), G[i].end(), [](Edge &x, Edge &y){return x.r < y.r;});dis[1] = 0;dfs(1, 0);for(int i=1; i<=n; i++){if(dis[i] == 1e9) cout << "-1\n";else cout << dis[i] << "\n";}
}
这篇关于[USACO23FEB] Moo Route II S 题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!