【洛谷】AT_abc373_d [ABC373D] Hidden Weights 的题解
题解
本地WA,提交AC,奇迹 AT,奇迹评测机
题目大意:
给定 n n n 个点, m m m 条有向边,每条有向边从 u i u_i ui 指向 v i v_i vi,边权为 w i w_i wi。构造一个长度为 n n n 的整数序列 x x x,满足: x v j − x u j = w j x_{v_j}−x_{u_j}=w_j xvj−xuj=wj
一个简单的 DFS?也不知道该叫啥qaq
注意到数据保证有解,因此一定有多组的解(在某组解上同时加或减一个数,差显然不变),构造起来也比较容易。直接遍历全图,对于当前的第
j
j
j 条边,若
v
j
v_j
vj 未遍历,则令
x
v
j
←
x
u
j
+
w
j
x_{v_j}\gets x_{u_j} + w_j
xvj←xuj+wj 即可,并遍历
v
j
v_j
vj。
对于图的每个连通分量,一旦在其中任何顶点上的值固定,则所有写入的值都是确定的。
我们可以逐个 DFS 每个连通分量,按照题目的要求给每个点赋值,初始搜索的点值设成 0 0 0 即可。
不开 long long 见祖宗,C题刚被坑,D题学乖了
代码
#include <bits/stdc++.h>
#define lowbit(x) x & (-x)
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace fastIO {
inline int read() {
register int x = 0, f = 1;
register char c = getchar();
while (c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void write(int x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
return;
}
}
using namespace fastIO;
struct edge {
ll v, w, nextt;
}e[1000005];
ll n, m, head[1000005], vis[1000005], ans[1000005], tot;
void dfs(int u) {
vis[u] = 1;
int v;
for(int i = head[u]; i; i = e[i].nextt) {
v = e[i].v;
if(vis[v]) {
continue;
}
ans[v] = ans[u] + e[i].w;
dfs(v);
}
return;
}
void add(int u, int v, int w) {
tot ++;
e[tot].v = v;
e[tot].w = w;
e[tot].nextt = head[u];
head[u] = tot;
return;
}
int main() {
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(ll i = 1; i <= m; i ++) {
ll u, v, w;
cin >> u >> v >> w;
add(u, v, w);
add(v, u, -w);
}
for(ll i = 1; i <= n; i ++) {
if(!vis[i]) {
dfs(i);
}
}
for(ll i = 1; i <= n; i ++) {
cout << ans[i] << " ";
}
return 0;
}