【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\n"); 41 else printf("false\n"); 42 } 43 return 0; 44 }