【洛谷】AT_abc373_c [ABC373D] Hidden Weights 的题解

【洛谷】AT_abc373_c [ABC373D] Hidden Weights 的题解

洛谷传送门

AT传送门

题解

本地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 xvjxuj=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 xvjxuj+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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值