题目大意:
给出一本
n
n
n个月的账本,
m
m
m个提示
(
l
,
r
,
w
)
(l,r,w)
(l,r,w)表示第
l
l
l到
r
r
r月的收入总和为
w
w
w,为这个账本是否合法, 即提示是否存在冲突。
数据有
T
T
T组。
n
<
100
,
m
<
1000
,
T
<
100
n<100,m<1000,T<100
n<100,m<1000,T<100
分析:
设点
i
i
i表示前
i
i
i个月的收入总和,
则对于一个提示
(
l
,
r
,
w
)
(l,r,w)
(l,r,w),即前
r
r
r个月比前
l
−
1
l-1
l−1个月的收入总和要多了
w
w
w,
规定了
权
值
r
=
权
值
l
−
1
+
w
权值_r=权值_{l-1}+w
权值r=权值l−1+w,
那么我们把这个限制弄成不等式,
即
连边
(
r
)
−
>
(
l
−
1
)
(r)->(l-1)
(r)−>(l−1),边权为
−
w
-w
−w
连边
(
l
−
1
)
−
>
(
r
)
(l-1)->(r)
(l−1)−>(r),边权为
w
w
w
那就是一个裸的差分约束系统了
判定一下负环即可
代码:
#include <iostream>
#include <cstring>
#include <queue>
#include <cmath>
#include <cstdio>
#include <algorithm>
#define N 105
using namespace std;
struct Node { int To, w, nxt; }e[N*20];
int dis[N], Ru[N], ls[N], n, m, T, cnt;
bool vis[N];
void Addedge(int u, int v, int w)
{
e[++cnt].To = v, e[cnt].nxt = ls[u], e[cnt].w = w, ls[u] = cnt;
}
queue <int> Q;
bool spfa()
{
for (int i = 0; i <= n; i++) dis[i] = 0;
while (Q.size()) Q.pop();
for (int i = 0; i <= n; i++) Q.push(i), vis[i] = 1, Ru[i] = 1;
while (!Q.empty())
{
int u = Q.front(); Q.pop();
for (int i = ls[u]; i; i = e[i].nxt)
if (dis[u] + e[i].w > dis[e[i].To])
{
dis[e[i].To] = dis[u] + e[i].w;
if (!vis[e[i].To])
{
vis[e[i].To] = 1, Q.push(e[i].To), ++Ru[e[i].To];
if (Ru[e[i].To] > n) return 0;
}
}
vis[u] = 0;
}
return 1;
}
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &n, &m);
for (int i = 0; i <= n; i++) ls[i] = 0;
cnt = 0;
for (int i = 1; i <= m; i++)
{
int l, r, value; scanf("%d %d %d", &l, &r, &value);
Addedge(r, l - 1, -value), Addedge(l - 1, r, value);
}
if (spfa()) printf("true\n"); else printf("false\n");
}
return 0;
}