题意
给定一个有向图
这条路径的权值是这条路径上边的权值之和
思路
思路有两种
总结一点经验
正解是第一种dijkstra
的算法
感觉正确的做法是
其实两种思路的边界似乎也没有这么清晰
修改最短路算法
对每个节点
假定现在已知原图中某个节点的全部状态的值
只差一步了
1->2 a:100 b:99
1->3 a:1 b:0
3->1 a:1 b:0
从1到2的最优路径是1->3->1->2
感觉上讲
这就是我们思考的终点
修改图
修改图的意思就是修改图使得原问题变成新图上裸的单源最短路问题
其实我们的思考也没有结束
需要注意到这样一件事
我赛中思考了新图应有的特征if
现在说正解
总结一下
令特权节点与入边一一对应看起来有一定的单调性
AC代码
#include <bits/stdc++.h>
#define maxn 100005
#define INF 0x3f3f3f3f3f3f3f3fLL
using namespace std;
typedef long long ll;
struct edge {
ll from, to, a, b;
bool operator<(const edge& e_) const {
return a < e_.a;
}
};
typedef vector<edge> ve;
typedef pair<ll, ll> pll;
ve nodeList[maxn];
ve G[maxn * 3];
ll cnt;
ll d[maxn * 3], ans[maxn];
ll demap[maxn * 3];
priority_queue<pll, vector<pll>, greater<pll> > pq;
bool vis[maxn * 3];
int main()
{
cin.tie(0)->sync_with_stdio(0);
ll T, n, m;
cin >> T;
while (T-- > 0) {
cin >> n >> m;
for (ll i = 1; i <= n; ++i) {
nodeList[i].clear();
ans[i] = INF;
demap[i] = i;
}
for (ll i = 1; i <= n + m; ++i) {
G[i].clear();
vis[i] = false;
d[i] = INF;
}
cnt = n;
for (ll i = 1; i <= m; ++i) {
ll u, v, a, b;
cin >> u >> v >> a >> b;
cnt += 1;
demap[cnt] = u;
nodeList[u].push_back(edge{cnt, v, a, b});
}
for (ll i = 1; i <= n; ++i) {
sort(nodeList[i].begin(), nodeList[i].end());
}
for (ll i = 1; i <= n; ++i) {
for (ll j = 0; j < nodeList[i].size(); ++j) {
edge &e = nodeList[i][j];
auto iter = upper_bound(nodeList[e.to].begin(), nodeList[e.to].end(), e);
if (iter == nodeList[e.to].end()) {
G[i].push_back(edge{i, e.to, e.a, -1}); // -1 in this new edge is useless
} else {
G[i].push_back(edge{i, iter->from, e.a, -1});
}
e.a -= e.b;
if (iter == nodeList[e.to].end()) {
G[e.from].push_back(edge{e.from, e.to, e.a, -1}); // -1 in this new edge is useless
} else {
G[e.from].push_back(edge{e.from, iter->from, e.a, -1});
}
if (j + 1 != nodeList[i].size()) {
G[e.from].push_back(edge{e.from, nodeList[i][j + 1].from, 0, -1});
} else {
G[e.from].push_back(edge{e.from, i, 0, -1});
}
e.a += e.b;
}
}
d[1] = 0;
pq.push(pll(0, 1));
while (!pq.empty()) {
pll top = pq.top(); pq.pop();
ll u = top.second, dis = top.first;
if (vis[u]) continue;
vis[u] = true;
d[u] = dis;
ans[demap[u]] = min(ans[demap[u]], dis);
for (auto e : G[u]) {
ll v = e.to;
if (dis + e.a < d[v]) {
pq.push(pll(dis + e.a, v));
}
}
}
for (int i = 1; i < n; ++i) {
cout << (ans[i] == INF ? -1 : ans[i]) << ' ';
}
cout << (ans[n] == INF ? -1 : ans[n]) << '\n';
}
return 0;
}