1. 程式人生 > >[luogu P2294] [HNOI2005]狡猾的商人

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

return log txt -a () class oid color 信息

[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:

技術分享
 1 %:pragma GCC optimize(2)
 2 #include<bits/stdc++.h>
 3 #define Ms(a,x) memset(a,x,sizeof a)
 4 using namespace std;
 5 const int N=105,M=2005;
 6 int n,m,inf,tot,tag; bool vis[N];
 7 int lnk[N],nxt[M],son[M],w[M],dis[N];
 8 inline int read() {
 9     int x=0,f=1; char ch=getchar();
10 while (ch<0||ch>9) f=(ch==-)?-1:1,ch=getchar(); 11 while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar(); 12 return x*f; 13 } 14 void add(int x,int y,int z) { 15 nxt[++tot]=lnk[x],lnk[x]=tot,son[tot]=y,w[tot]=z; 16 } 17 void spfa(int x) { 18 vis[x]=1; 19 for (int j=lnk[x]; j; j=nxt[j]) 20 if (dis[son[j]]<dis[x]+w[j]) { 21 dis[son[j]]=dis[x]+w[j]; 22 if (vis[son[j]]) {tag=0; return;} 23 vis[son[j]]=1,spfa(son[j]); 24 } 25 vis[x]=0; 26 } 27 int main() { 28 for (int T=read(); T; T--) { 29 n=read(),m=read(),tag=1,tot=0,Ms(lnk,0),Ms(nxt,0); 30 for (int i=1,x,y,z; i<=m; i++) 31 x=read()-1,y=read(),z=read(),add(x,y,z),add(y,x,-z); 32 Ms(vis,0),Ms(dis,63); 33 for (int i=0; i<=n; i++) {spfa(i); if (!tag) break;} 34 puts(tag?"true":"false"); 35 } 36 return 0; 37 }
View Code

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