背景(中文版):打开mooc发现ddl在昨天已经过了(今日真实事件),于是准备穿越各个教学楼里的一些虫洞回到昨天来补救一下。
题意:给定n个点,m条双向正边,w条单向负边,问图中有没有负环。
代码:
1 #include<stdio.h> 2 #include <algorithm> 3 #include <queue> 4 using namespace std; 5 #define ll long long 6 #define maxx 3005 7 #define inf 0x7fffffff 8 //#define int long long 9 struct edge{ 10 int u,v,w; 11 int nxt; 12 }e[maxx*2]; 13 int head[maxx]={0},cnt=0; 14 void add(int u,int v,int w){ 15 e[++cnt].u=u; 16 e[cnt].v=v; 17 e[cnt].w=w; 18 e[cnt].nxt=head[u]; 19 head[u]=cnt; 20 } 21 int n,m,w; 22 int in[maxx],dis[maxx],vis[maxx]; 23 int spfa(int x){ 24 for(int i=1;i<=n;i++) 25 in[i]=0,vis[i]=0; 26 for(int i=1;i<=n;i++) 27 dis[i]=inf; 28 29 queue<int> q; 30 q.push(x); 31 vis[x]=1;dis[x]=0;in[x]++; 32 while(!q.empty()){ 33 int now=q.front(); 34 q.pop(); 35 vis[now]=0; 36 for(int i=head[now];i;i=e[i].nxt){ 37 int to=e[i].v; 38 int temp=dis[now]+e[i].w; 39 if(temp<dis[to]){ 40 dis[to]=temp; 41 in[to]++; 42 if(in[to]>=n) 43 return 1; 44 if(!vis[to]){ 45 q.push(to); 46 vis[to]=1; 47 } 48 } 49 } 50 } 51 return 0; 52 } 53 signed main() { 54 int T; 55 scanf("%d",&T); 56 while(T--){ 57 memset(e,0,sizeof e); 58 memset(head,0,sizeof head); 59 cnt=0; 60 scanf("%d%d%d",&n,&m,&w); 61 for(int i=1;i<=m;i++){ 62 int x,y,z; 63 scanf("%d%d%d",&x,&y,&z); 64 add(x,y,z); 65 add(y,x,z); 66 } 67 for(int i=0;i<w;i++){ 68 int x,y,z; 69 scanf("%d%d%d",&x,&y,&z); 70 add(x,y,-z); 71 } 72 for(int i=1;i<=n;i++){ 73 if(spfa(i)){ 74 printf("YES\n"); 75 goto nxt; 76 } 77 } 78 printf("NO\n"); 79 nxt:; 80 } 81 return 0; 82 }