「HNOI2005」狡猾的商人
阿新 • • 發佈:2018-04-21
trade pan new push n-1 pro cstring out 記錄
題目描述
刁姹接到一個任務,為稅務部門調查一位商人的賬本,看看賬本是不是偽造的。賬本上記錄了n個月以來的收入情況,其中第i 個月的收入額為Ai(i=1,2,3...n-1,n), 。當 Ai大於0時表示這個月盈利Ai 元,當 Ai小於0時表示這個月虧損Ai 元。所謂一段時間內的總收入,就是這段時間內每個月的收入額的總和。 刁姹的任務是秘密進行的,為了調查商人的賬本,她只好跑到商人那裏打工。她趁商人不在時去偷看賬本,可是她無法將賬本偷出來,每次偷看賬本時她都只能看某段時間內賬本上記錄的收入情況,並且她只能記住這段時間內的總收入。 現在,刁姹總共偷看了m次賬本,當然也就記住了m段時間內的總收入,你的任務是根據記住的這些信息來判斷賬本是不是假的。
鏈接
BZOJ 1202
luogu 2294
題解
算法1 (差分約束系統)
思路
l
,r
,s
,表示從l
到r
的和是s
- 維護前綴和 \(sum_i=\sum\limits_{j=1}^{i}A_j\)
- 於是可以將
l-1
和r
連一條-s
的邊,r
和l-1
連一條s
的邊,即保證 \(sum_r-sum_{l-1}=s\) - 最後跑 spfa 判斷是否有負環
代碼
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define MAXN 105
using namespace std;
typedef pair <int,int> pii;
typedef long long ll;
int T,n,m,Q[MAXN],cnt[MAXN];
ll dis[MAXN];
bool vis[MAXN],flg;
vector <pii> e[MAXN];
void spfa(int s){
int H=0,T=1;
Q[1]=s,vis[s]=1,dis[s]=0;
while (H!=T){
int x=Q[++H%=MAXN]; vis[x]=0 ; cnt[x]++;
if (cnt[x]>n){
flg=1;
return;
}
for (int i=0;i<e[x].size();i++){
int v=e[x][i].first;
if (dis[x]+e[x][i].second<dis[v]){
dis[v]=dis[x]+e[x][i].second;
if (!vis[v]){
vis[v]=1;
Q[++T%=MAXN]=v;
}
}
}
}
}
int main(){
freopen("trader.in","r",stdin);
freopen("trader.out","w",stdout);
scanf("%d",&T);
while (T--){
memset(dis,63,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
memset(Q,0,sizeof(Q));
flg=0;
scanf("%d%d",&n,&m);
for (int i=0;i<=n;i++) e[i].clear();
for (int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
e[u-1].push_back(make_pair(v,-w));
e[v].push_back(make_pair(u-1,w));
}
for (int i=1;i<=n;i++){
if (!cnt[i]) spfa(i);
if (flg) break;
}
if (flg)
puts("false");
else
puts("true");
}
return 0;
}
「HNOI2005」狡猾的商人