Codeforces Round #722 (Div. 1) D. It’s a bird! No, it’s a plane! No, it’s AaParsa!(最短路)
链接
题意:给一个带权有向图,但是每经过
1
s
1s
1s这条路的终点就会变成
(
v
+
s
)
%
n
(v+s)\%n
(v+s)%n,v是原来的终点,s是经过的时间,时间是权值,我们可以在任意节点等待任意时间。
思路:我们可以想到的是,如果等待
1
s
1s
1s,那么就相当于多了一条
v
→
v
+
1
v\to v+1
v→v+1的边,所以到达每个点的时候我们用这条边来更新一下答案,然后因为有时间,转移是
v
=
(
e
[
i
]
.
t
o
+
d
i
s
[
u
]
)
%
n
v=(e[i].to+dis[u])\%n
v=(e[i].to+dis[u])%n,特别的,因为我们第一个点没有
v
→
v
+
1
v\to v+1
v→v+1这条边,所以我们要提前更新第一个点,并且不能刻意把起点的dis初始化为0,不然会更新
s
t
+
1
st+1
st+1的距离
#include<bits/stdc++.h>
using namespace std;
#define int long long
int dis[650], vis[650], f[650][650], n, m;
int head[650], idx;
struct Edge{int to, nxt, d;}e[1000010];
void add(int u, int v, int d) {e[++idx].to = v, e[idx].nxt = head[u], e[idx].d = d, head[u] = idx;}
void dijstra(int st)
{
memset(vis, 0, sizeof (vis));
memset(dis, 0x3f, sizeof (dis));
for (int i = head[st]; i; i = e[i].nxt) {dis[e[i].to] = e[i].d;}
for (int i = 0; i < n; i++) {
int t = -1;
for (int j = 0; j < n; j++) {
if (!vis[j] && (t == -1 || dis[t] > dis[j])) {
t = j;
}
}
if(t == -1) break;
vis[t] = 1;
dis[(t + 1) % n] = min(dis[t] + 1, dis[(t + 1) % n]);
for (int j = head[t]; j; j = e[j].nxt) {
int v = e[j].to, d = e[j].d;
v = (v + dis[t]) % n;
dis[v] = min(dis[v], dis[t] + d);
}
}dis[st] = 0;
for (int i = 0; i < n; i++) cout << dis[i] << ' ' ; cout << endl;
}
signed main()
{
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v, d;
cin >> u >> v >> d;
add(u, v, d);
}
for (int st = 0; st < n; st++) {
dijstra(st);
}
return 0;
}