洛谷P2294 [HNOI2005]狡猾的商人
阿新 • • 發佈:2018-12-31
etc class int tchar esp getchar ron main inline 總是小於等於\(t\)。
即可,如果說在第i組詢問中存在負環,說明第\(i\)本賬本是假的,輸出\(false\),否則輸出\(true\)。
題目描述
輸入輸出格式
輸入格式:
從文件\(input.txt\)中讀入數據,文件第一行為一個正整數\(w\),其中\(w < 100\),表示有\(w\)組數據,即\(w\)個賬本,需要你判斷。每組數據的第一行為兩個正整數\(n\)和\(m\),其中\(n < 100,m < 1000\),分別表示對應的賬本記錄了多少個月的收入情況以及偷看了多少次賬本。接下來的\(m\)行表示刁姹偷看\(m\)次賬本後記住的\(m\)條信息,每條信息占一行,有三個整數\(s\),\(t\)和\(v\),表示從第\(s\)個月到第\(t\)個月(包含第\(t\)個月)的總收入為\(v\),這裏假設\(s\)
輸出格式:
輸出文件\(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
思路:題目中的條件可以轉化為\(v \leq d[t]-d[s] \leq v\),這就是這個題目中唯一的約束條件,然後對於每組詢問建邊,跑\(spfa\)
代碼:
#include<cstdio> #include<algorithm> #include<cctype> #include<cstring> #include<queue> #define maxn 100007 using namespace std; int num,t,n,m,head[maxn],dis[maxn],vis[maxn],in[maxn]; inline int qread() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num*f; } struct node { int v,w,nxt; }e[200007]; inline void ct(int u, int v, int w) { e[++num].v=v; e[num].w=w; e[num].nxt=head[u]; head[u]=num; } inline bool spfa() { memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(in,0,sizeof(in)); queue<int>q; q.push(0),vis[0]=1,in[0]=1,dis[0]=0; while(!q.empty()) { int u=q.front(); q.pop(),vis[u]=0; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; if(!vis[v]) { vis[v]=1; in[v]++; if(in[v]>n) return 1; q.push(v); } } } } return 0; } int main() { t=qread(); while(t--) { n=qread(),m=qread(); memset(head,0,sizeof(head)); num=0; for(int i=1,u,v,w;i<=m;++i) { u=qread(),v=qread(),w=qread(); ct(u-1,v,w),ct(v,u-1,-w); } if(spfa()) printf("false\n"); else printf("true\n"); } return 0; }
洛谷P2294 [HNOI2005]狡猾的商人