比赛地址nbhttps://acm.hdu.edu.cn/contest/login?cid=1044&redirect=/contest/problems%3Fcid%3D1044
H Path
题目大意:给你一张单向图,存在两种路径一中是普通的带权路,还有一种特殊路径,经过特殊路径后可以飞往与特殊路径不相邻的任意一点,或经过相邻路径且减少k的代价。
作法:用set储存没有确定最短路的点,对于非相邻点我们可以直接更新,相邻点则让边权减去k然后正常做最短路。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
using namespace std;
using ll = long long;
const int N = 1e6+10, M = N;
const ll INF = 1e18;
int h[N], e[M], w[M], ne[M], type[M], idx;
struct Node {
ll id, dis, type;
bool operator<(const Node &t) const {
return dis > t.dis;
}//优先队列存结构体只能重构<
};
bool st[N][2];
ll dist[N][2];
int close[N];//用来标记领边
void add(int a, int b, int c, int d) {
e[idx] = b, w[idx] = c, type[idx] = d, ne[idx] = h[a], h[a] = idx++;
}
int n, m, s, k;
void BFS() {
set<int> S;//S中存还未确定最短路的点
for (int i = 1; i <= n; i++) {
if (i != s) S.insert(i);
st[i][0] = st[i][1] = false;
dist[i][0] = dist[i][1] = INF;
}
dist[s][0]=0;
priority_queue<Node>q;
q.push({s,0,0});
int cnt=0;
while(!q.empty())
{
auto t=q.top();
q.pop();
int ty=t.type,ver=t.id;
cnt++;
if(!ty) S.erase(ver); //如果是正常道路就正常做
else
{
for(int i=h[ver];~i;i=ne[i])
{
int j=e[i];
close[j]=cnt; //都是cnt号的领边
}
vector<int>tmp;
for(auto it:S)
{
if(close[it]!=cnt) // 非相邻的点
{
tmp.push_back(it);
dist[it][0]=dist[ver][ty];
q.push({it,dist[it][0],0});
}
}
for(auto it : tmp) S.erase(it); // 被更新的点被遍历过 所以直接删除
}
int y=0;
if(ty) y-=k;
if(st[ver][ty]) continue;
st[ver][ty]=true;
for(int i = h[ver] ; ~i ; i = ne[i])
{
int j = e[i];
if(dist[j][type[i]] > dist[ver][ty] + w[i] + y)
{
dist[j][type[i]] = dist[ver][ty] + w[i] + y;
q.push({j, dist[j][type[i]], type[i]});
}
}
}
}
void Solve() {
cin >> n >> m >> s >> k;
memset(h, -1, sizeof(h));
memset(close, -1, sizeof(close));
while (m--) {
int a, b, c, d;
cin >> a >> b >> c >> d;
add(a, b, c, d);
}
BFS();
for (int i = 1; i <= n; i++)
if (min(dist[i][0], dist[i][1]) == INF) cout << -1 << " ";
else cout << min(dist[i][0], dist[i][1]) << " ";
cout << "\n";
}
int main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
Solve();
}
如果看不懂可以直接看这位大佬的题解,给了我很大帮助