洛谷P2294 [HNOI2005]狡猾的商人
\(\large{题目链接}\)
\(\\\)
\(\Large\textbf{Solution: } \large{1.因为每次提供的是一段时间的利润,具体的每个月并不清楚,所以考虑直接判断前缀和是否合法即可。\\2.可以考虑带权并查集,设\text{top[x] = pre[find(x)] - pre[x]},然后每次操作如果在一个集合里,就直接判断是否合法,如果不在,那就更新\text{top}值。}\)
\(\\\)
\(\Large\textbf{Summary: } \large{像这种判断是否合法或者两者之间关系的题目,可以往图上想一想。}\)
\(\\\)
\(\Large\textbf{Code: }\)
#include <bits/stdc++.h>
#define gc() getchar()
#define LL long long
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _rep(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
const int N = 105;
const int M = 1005;
const int inf = 0x7fffffff;
int w, n, m, cnt, head[N], vis[N], r[N], dis[N];
struct Edge {
int to, next, val;
}e[M << 1];
inline int read() {
int x = 0, flg = 1;
char ch = gc();
while (!isdigit(ch)) {
if (ch == '-') flg = -1;
ch = gc();
}
while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
return x * flg;
}
inline void add(int x, int y, int w) {
e[++cnt].to = y;
e[cnt].val = w;
e[cnt].next = head[x];
head[x] = cnt;
}
inline bool Spfa() {
queue <int> q;
memset(vis, 0, sizeof (vis));
rep(i, 0, n) dis[i] = inf;
dis[0] = 0; vis[0] = 1; q.push(0);
while (!q.empty()) {
int x = q.front(); q.pop();
vis[x] = 0;
for (int i = head[x]; i ; i = e[i].next) {
int u = e[i].to;
if (dis[u] == inf) {
dis[u] = dis[x] + e[i].val;
if (!vis[u]) vis[u] = 1, q.push(u);
}
else if (dis[u] != dis[x] + e[i].val) return false;
}
}
return true;
}
int main() {
w = read();
while (w--) {
cnt = 0;
memset(head, 0, sizeof (head));
n = read(), m = read();
int x, y, w;
while (m--) x = read(), y = read(), w = read(), add(x - 1, y, w), add(y, x - 1, -w);
int flg = Spfa();
flg ? puts("true") : puts("false");
}
return 0;
}
\(\\\)
\(\Large\textbf{Code: }\)
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int t, n, m, f[N], top[N];
inline int read() {
int x = 0, flg = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') flg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
return x * flg;
}
inline void init() { for (int i = 0; i <= n; ++i) f[i] = i, top[i] = 0; }
inline int find(int x) {
if (x == f[x]) return x;
int temp = find(f[x]);
top[x] += top[f[x]];
return f[x] = temp;
}
int main() {
t = read();
while (t--) {
n = read(), m = read();
init(); int x, y, w, flg = 0;
while (m--) {
x = read() - 1, y = read(), w = read();
int X = find(x), Y = find(y);
if (X != Y) {
top[X] = top[y] - top[x] - w;//top[X] = pre[Y] - pre[X], pre[Y] - pre[y] = top[y], pre[y] = pre[x] + w, top[x] = pre[X] - pre[x]
f[X] = Y;
} else if (top[y] - top[x] != w) { flg = 1; break; }
}
flg ? puts("false") : puts("true");
}
return 0;
}