【题目描述】:
现在有n (1<=N<=500)个点,m(1<=M<=2500)条边(双向),代表现在可以走的通路,比如从a到b和从b到a需要花费c时间,现在在地上出现了w (1<=W<=200)个虫洞(单向),虫洞的意义就是你从a到b话费的时间是-c(时间倒流,并且虫洞是单向的),现在问你从某个点开始走,能否回到从前。
【输入描述】:
第一行一个整数F,表示测试组数。 (1<=F<=5)
每组数据第一行,三个用空格隔开的正整数,表示 n,m,w
以下m行,每行三个正整数,表示双向的正常通路的两个点和所用的时间。
以下w行,每行三个正整数,表示单向的虫洞的两个点和倒流的时间。
【输出描述】:
对于每组数据。输出NO或YES表示是否可以实现回到起点的过去。
【样例输入】:
2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8
【样例输出】:
NO
YES
【时间限制、数据范围及描述】:
时间:1s 空间:128M
数据规模如题中所述
题解:判负环ooo~
#include<cstdio> #include<iostream> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<bits/stdc++.h> typedef long long ll; using namespace std; const int N=12020; int yc,TT,n,m,cnt,x,y,z; int tot[N],dis[N],vis[N],head[N]; struct node{ int to,next,w; }e[N]; void add(int u,int v,int w){ e[++cnt].to=v; e[cnt].w=w; e[cnt].next=head[u]; head[u]=cnt; } queue<int> q; bool spfa(){ queue<int>q; memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); memset(tot,0,sizeof(tot)); dis[1]=0; vis[1]=1; q.push(1); while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(dis[v]>dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; if(!vis[v]) { q.push(v); vis[v]=1; tot[v]++; } } if(tot[v]>=n) return 1; } } return 0; // if(dis[t]!=0x3f3f3f3f) return dis[t]; // else return -1; } int main(){ // freopen("chdong.in","r",stdin); // freopen("chdong.out","w",stdout); scanf("%d",&TT); while(TT--){ cnt=0; scanf("%d %d %d",&n,&m,&yc); memset(head,0,sizeof(head)); for(int i=1;i<=m;i++){ scanf("%d %d %d",&x,&y,&z); add(x,y,z); add(y,x,z); } for(int i=1;i<=yc;i++){ scanf("%d %d %d",&x,&y,&z); add(x,y,-z); } if(spfa()==1) printf("YES "); else printf("NO "); //cout<<spfa(x,y)<<endl; } return 0;