【BZOJ1202】【HNOI2005】狡猾的商人

查分约束好,好写好调好AC!

原题:

刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的。账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), 。当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai 元。所谓一段时间内的总收入,就是这段时间内每个月的收入额的总和。 刁姹的任务是秘密进行的,为了调查商人的账本,她只好跑到商人那里打工。她趁商人不在时去偷看账本,可是她无法将账本偷出来,每次偷看账本时她都只能看某段时间内账本上记录的收入情况,并且她只能记住这段时间内的总收入。 现在,刁姹总共偷看了m次账本,当然也就记住了m段时间内的总收入,你的任务是根据记住的这些信息来判断账本是不是假的。

n < 100,m < 1000

这题可以查分约束也可以用并查集,不过并查集的做法比较神奇,我暂时还不能理解,所以用差分约束水

a到b的收益为w,另sa等于从开始到a的收益,那么sb-s(a-1)=w

因为这本质是一个前缀和,所以要-1

差分约束搞即可

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 int rd(){int z=0,mk=1;  char ch=getchar();
 8     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
 9     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
10     return z*mk;
11 }
12 struct ddd{int nxt,y,v;}e[2100];  int lk[110],ltp=0;
13 inline void ist(int x,int y,int z){e[++ltp].nxt=lk[x],lk[x]=ltp,e[ltp].y=y,e[ltp].v=z;}
14 int n,m;
15 int dstc[110],cnt[110];
16 int q[1100000],tp=1000001,hd=0,tl=0;  bool vstd[110];
17 bool spfa(){
18     hd=0,tl=0;
19     for(int i=0;i<=n;++i)  q[++hd]=i,vstd[i]=true,cnt[i]=0,dstc[i]=0;
20     while(tl!=hd){
21         tl=(tl==tp ? 0 : tl+1);
22         for(int i=lk[q[tl]];i;i=e[i].nxt)if(dstc[q[tl]]+e[i].v>dstc[e[i].y]){
23             dstc[e[i].y]=dstc[q[tl]]+e[i].v;
24             if(++cnt[e[i].y]==n)  return false;
25             if(!vstd[e[i].y])  q[hd=(hd==tp ? 0 : hd+1)]=e[i].y,vstd[e[i].y]=true;
26         }
27         vstd[q[tl]]=false;
28     }
29     return true;
30 }
31 void clr(){  memset(lk,0,sizeof(lk)),ltp=0;}
32 int main(){//freopen("ddd.in","r",stdin);
33 int T;  cin>>T;  while(T--){  clr();
34     n=rd(),m=rd();
35     int l,r,v;
36     while(m--){
37         l=rd(),r=rd(),v=rd();
38         ist(l-1,r,v),ist(r,l-1,-v);
39     }
40     if(spfa())  printf("true
");
41     else  printf("false
");
42 }
43     return 0;
44 }
View Code
原文地址:https://www.cnblogs.com/JSL2018/p/6539593.html