[luogu P2294] [HNOI2005]狡猾的商人

时间:2023-03-08 23:11:03
[luogu P2294] [HNOI2005]狡猾的商人

[luogu P2294] [HNOI2005]狡猾的商人

题目描述

[luogu P2294] [HNOI2005]狡猾的商人

输入输出格式

输入格式:

从文件input.txt中读入数据,文件第一行为一个正整数w,其中w < 100,表示有w组数据,即w个账本,需要你判断。每组数据的第一行为两个正整数n和m,其中n < 100,m < 1000,分别表示对应的账本记录了多少个月的收入情况以及偷看了多少次账本。接下来的m行表示刁姹偷看m次账本后记住的m条信息,每条信息占一行,有三个整数s,t和v,表示从第s个月到第t个月(包含第t个月)的总收入为v,这里假设s总是小于等于t。

输出格式:

输出文件output.txt中包含w行,每行是true或false,其中第i行为true当且仅当第i组数据,即第i个账本不是假的;第i行为false当且仅当第i组数据,即第i个账本是假的。

输入输出样例

输入样例#1:
2
3 3
1 2 10
1 3 -5
3 3 -15
5 3
1 5 100
3 5 50
1 2 51
输出样例#1:
true
false

显然这是一道差分题。。对于一个限制条件(x,y,z),要满足f[y]=f[x-1]+z,即f[y]>=f[x-1]+z&&f[y]<=f[x-1]+z。

稍微变形得f[y]>=f[x-1]+z&&f[x-1]>=f[y]-z。也就是说,需要建一条x-1到y,权值为z的边和y到x-1,权值为-z的边,然后跑一个最短路。

如果出现了负权回路就GG。对于这一题,我采用了dfs版的spfa,更简便且适用于这题。

code:

 %:pragma GCC optimize()
 #include<bits/stdc++.h>
 #define Ms(a,x) memset(a,x,sizeof a)
 using namespace std;
 ,M=;
 int n,m,inf,tot,tag; bool vis[N];
 int lnk[N],nxt[M],son[M],w[M],dis[N];
 inline int read() {
     ,f=; char ch=getchar();
     :,ch=getchar();
     +ch-',ch=getchar();
     return x*f;
 }
 void add(int x,int y,int z) {
     nxt[++tot]=lnk[x],lnk[x]=tot,son[tot]=y,w[tot]=z;
 }
 void spfa(int x) {
     vis[x]=;
     for (int j=lnk[x]; j; j=nxt[j])
         if (dis[son[j]]<dis[x]+w[j]) {
             dis[son[j]]=dis[x]+w[j];
             ; return;}
             vis[son[j]]=,spfa(son[j]);
         }
     vis[x]=;
 }
 int main() {
     for (int T=read(); T; T--) {
         n=read(),m=read(),tag=,tot=,Ms(lnk,),Ms(nxt,);
         ,x,y,z; i<=m; i++)
             x=read()-,y=read(),z=read(),add(x,y,z),add(y,x,-z);
         Ms(vis,),Ms(dis,);
         ; i<=n; i++) {spfa(i); if (!tag) break;}
         puts(tag?"true":"false");
     }
     ;
 }