题解:P10193 [USACO24FEB] Bessla Motors G
KingPowers · · 题解
很考察对 dijkstra 算法流程理解程度的一道题。
注意到
先从特殊情况入手,如果
对于
对正确性的简要证明:思考 dijkstra 的算法流程,我们每次从堆顶取出来的一定是路径最短的点,因此每个点取出来的
对复杂度的简要证明:同样因为每次在堆顶取出来的是最短路,所以每个点至多被取出来向周围扩展
当然我懒得实现精细了,用 multiset 代替了堆,同时记录不同的源点路径用的是 map,可能会稍劣一些。
#include<bits/stdc++.h>
//#define int long long
#define For(i, a, b) for(int i = (a); i <= (b); i++)
#define Rof(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
using PII = pair<int, int>;
const int N = 5e5 + 5;
int n, m, c, k, r;
vector<PII> G[N];
map<int, bool> vis[N];
struct node{int id, dis, pre;};
bool operator<(const node &a, const node &b){
return a.dis < b.dis;
}
void dijkstra(){
multiset<node> st;
For(i, 1, c) st.insert({i, 0, i});
while(!st.empty()){
auto [now, dis, pre] = *st.begin();
st.erase(st.begin());
if(vis[now].size() >= k || vis[now].count(pre)) continue;
vis[now][pre] = 1;
for(auto [to, val] : G[now]){
int newd = dis + val;
if(newd > r || vis[to].size() >= k || vis[to].count(pre)) continue;
st.insert({to, newd, pre});
}
}
}
void Solve(){
cin >> n >> m >> c >> r >> k;
For(i, 1, m){
int u, v, w; cin >> u >> v >> w;
G[u].emplace_back(v, w);
G[v].emplace_back(u, w);
}
dijkstra();
vector<int> vec;
For(i, c + 1, n) if(vis[i].size() >= k)
vec.emplace_back(i);
cout << vec.size() << '\n';
for(int to : vec) cout << to << '\n';
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int T = 1; //cin >> T;
while(T--) Solve();
return 0;
}