狡猾的商人 bzoj 1202 差分约束系统

32 篇文章 0 订阅

题目大意

刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的。账本上记录了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");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值