题目大意
刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的。账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3…n-1,n), 。当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai 元。所谓一段时间内的总收入,就是这段时间内每个月的收入额的总和。 刁姹的任务是秘密进行的,为了调查商人的账本,她只好跑到商人那里打工。她趁商人不在时去偷看账本,可是她无法将账本偷出来,每次偷看账本时她都只能看某段时间内账本上记录的收入情况,并且她只能记住这段时间内的总收入。 现在,刁姹总共偷看了m次账本,当然也就记住了m段时间内的总收入,你的任务是根据记住的这些信息来判断账本是不是假的。
分析
差分约束系统
设a[x]表示前x个月一共的收入
要满足m个等式a[y]-a[x-1]=z
因为查分约束系统只能处理不等式,所以就把等式转变成两个不等式
a[y]-a[x-1]>=z
a[y]-a[x-1]<=z
然后就是裸的查分约束系统了
code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
struct arr{
int x,y,w,next;
}edge[5010];
int q[10010];
int ls[510];
int dis[510];
int v[510];
int sum[510];
int n,m;
int edge_m;
void add(int x,int y,int w)
{
edge_m++;
edge[edge_m]=(arr){x,y,w,ls[x]};ls[x]=edge_m;
}
int spfa()
{
for (int s=0;s<=n;s++)
{
for (int i=0;i<=n;i++) dis[i]=2000000000;
int head,tail;
memset(v,0,sizeof(v));
memset(sum,0,sizeof(sum));
head=0; tail=1;
dis[s]=0;
q[1]=s;
v[s]=1;
while (head<tail)
{
head++;
int x=q[head];
for (int i=ls[x];i;i=edge[i].next)
if (dis[edge[i].y]>dis[x]+edge[i].w)
{
dis[edge[i].y]=dis[x]+edge[i].w;
sum[edge[i].y]++;
if (sum[edge[i].y]>n)
return 0;
if (!v[edge[i].y])
{
v[edge[i].y]=1;
tail++;
q[tail]=edge[i].y;
}
}
v[x]=0;
}
}
return 1;
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&n,&m);
edge_m=0;
memset(edge,0,sizeof(edge));
memset(ls,0,sizeof(ls));
for (int i=1;i<=m;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
add(x-1,y,w);
add(y,x-1,-w);
}
if (spfa())
printf("true\n");
else
printf("false\n");
}
}