【洛谷 3385】负环
题目描述
暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索
寻找一个从顶点1所能到达的负环,负环定义为:一个边权之和为负的环。
输入格式
第一行一个正整数T表示数据组数,对于每组数据:
第一行两个正整数N M,表示图有N个顶点,M条边
接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w<0则为单向,否则双向)
输出格式
共T行。对于每组数据,存在负环则输出一行"YE5"(不含引号),否则输出一行"N0"(不含引号)。
输入输出样例
输入 #1
2 3 4 1 2 2 1 3 4 2 3 1 3 1 -3 3 3 1 2 3 2 3 4 3 1 -8
输出 #1
N0 YE5
说明/提示
n\leq 2000n≤2000
m\leq 3000m≤3000
-10000\leq w\leq 10000−10000≤w≤10000
T\leq 10T≤10
建议复制输出格式中的字符串。 本题数据感谢@negiizhao的精心构造,请不要使用玄学算法 本题数据有更新
题解:蓝题不难系列……spfa判负权环啦。貌似可以水过去
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<queue> #include<bits/stdc++.h> using namespace std; const int N=30005; const int M=200010; int T,st=1; int cntt,n,m; bool flag,v[N]; int d[N],cnt[N]; int head[N],tot; struct node{ int to; int next; int val; }e[M]; void add(int x,int y,int z){ e[++cntt].to=y; e[cntt].val=z; e[cntt].next=head[x]; head[x]=cntt; } bool spfa(){ queue<int> q; memset(d,0x3f,sizeof(d)); memset(v,0,sizeof(v)); d[st]=0;v[st]=1,cnt[st]=1; q.push(st); while(q.size()){ int x=q.front(); q.pop(); v[x]=0; for(int i=head[x];i;i=e[i].next){ int y=e[i].to; if(d[y]>d[x]+e[i].val){ d[y]=d[x]+e[i].val; cnt[y]=cnt[x]+1; if(cnt[y]>n) return 1; if(!v[y]) { v[y]=1; q.push(y); } } } } return 0; } int main(){ freopen("3385.in","r",stdin); freopen("3385.out","w",stdout); scanf("%d",&T); while(T--){ scanf("%d %d",&n,&m); memset(head,0,sizeof(head)); tot=0; int x,y,w; for(int i=1;i<=m;i++){ scanf("%d %d %d",&x,&y,&w); add(x,y,w); if(w>=0) add(y,x,w); } if(spfa()) puts("YE5"); else puts("N0"); } }