洛谷P3385 【模板】负环

题目描述

暴力枚举/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 2000n2000m\leq 3000m3000-10000\leq w\leq 1000010000w10000T\leq 10T10建议复制输出格式中的字符串。 本题数据感谢@negiizhao的精心构造,请不要使用玄学算法 本题数据有更新

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<queue>
  6 using namespace std;
  7 long long read()
  8 {
  9     long long x=0,f=1;
 10     char ch=getchar();
 11     while(ch>'9'||ch<'0')
 12     {
 13         if(ch=='-')
 14             f=-1;
 15         ch=getchar();
 16     }
 17     while(ch>='0'&&ch<='9')
 18     {
 19         x=x*10+ch-'0';
 20         ch=getchar();
 21     }
 22     return x*f;
 23 }
 24 const int maxn=20005;
 25 const int maxm=100010;
 26 int T,st=1,n,m,num;
 27 bool flag;
 28 bool vis[maxn];
 29 int dis[maxn],cnt[maxn],head[maxn],q[maxn];
 30 struct node
 31 {
 32     int v,w,nxt;
 33 } e[maxm*2];
 34 void add(int x,int y,int z)
 35 {
 36     e[++num].v=y;
 37     e[num].w=z;
 38     e[num].nxt=head[x];
 39     head[x]=num;
 40 }
 41 bool spfa()
 42 {
 43     int l=0,r=0;
 44     memset(dis,0x3f,sizeof(dis));
 45     memset(vis,0,sizeof(vis));
 46     memset(cnt,0,sizeof(cnt));
 47     memset(q,0,sizeof(q));
 48     vis[st]=1;
 49     cnt[st]=1;
 50     dis[st]=0;
 51     q[r++]=st;
 52     while(l!=r)
 53     {
 54         int u=q[l++];
 55         if(l>n)
 56             l=0;
 57         vis[u]=false;
 58         for(int i=head[u]; i; i=e[i].nxt)
 59         {
 60             if(dis[e[i].v]>dis[u]+e[i].w)
 61             {
 62                 dis[e[i].v]=dis[u]+e[i].w;
 63                 cnt[e[i].v]=cnt[u]+1;
 64                 if(cnt[e[i].v]>=n&&e[i].w<0)
 65                     return 1;
 66                 if(!vis[e[i].v])
 67                 {
 68                     vis[e[i].v]=1;
 69                     if(dis[e[i].v]>dis[q[l]])
 70                     {
 71                         l--;
 72                         if(l<0)
 73                             l=n;
 74                         q[l]=e[i].v;
 75                     }
 76                     else
 77                     {
 78                         q[r++]=e[i].v;
 79                         if(r>n)
 80                             r=0;
 81                     }
 82                 }
 83             }
 84         }
 85     }
 86     return false;
 87 }
 88 int main()
 89 {
 90     T=read();
 91     while(T--)
 92     {
 93         n=read(),m=read();
 94         memset(head,0,sizeof(head));
 95         num=0;
 96         for(int i=1; i<=m; i++)
 97         {
 98             int x=read(),y=read(),w=read();
 99             add(x,y,w);
100             if(w>=0)
101                 add(y,x,w);
102         }
103         if(spfa())
104             printf("YE5\n");
105         else
106             printf("N0\n");
107     }
108     return 0;
109 }
View Code

猜你喜欢

转载自www.cnblogs.com/liweilin/p/10227120.html