题意:有n个点,之间有m条双向路径,还有w个虫洞,单向,从一点到另一点需要花费时间,但是有虫洞的话会减少时间,一个人想要走某一条路使得他能碰到过去的自己,问这个图是否能让他实现他的想法。
其实就是判一个图是否存在负权值回路,SPFA可以实现,原理是:如果存在负权值回路,那么从源点到某个顶点的距离就可以无限缩短,因此就会无限入队,所以在SPFA中统计每个顶点的入队次数,如果超过了n个(顶点个数)则说明存在负权值回路。
我把输出yes和输出no写反了,WA了两发,看了半天都没发现。。。
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0) #define MAXN 30100 #define eps 1e-7 #define INF 0x7FFFFFFF #define seed 131 #define ll long long #define ull unsigned ll #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct node{ int u,v,next; }edge[MAXN]; queue<int>q; int dist[MAXN],head[MAXN],vis[MAXN],tot[MAXN]; int n,m,w,cnt,flag; void add_edge(int a,int b,int c){ edge[cnt].u = b; edge[cnt].v = c; edge[cnt].next = head[a]; head[a] = cnt++; } void spfa(){ int i,j; memset(vis,0,sizeof(vis)); vis[1] = 1; for(i=1;i<=n;i++) dist[i] = INF; dist[1] = 0; q.push(1); while(!q.empty()){ int temp = q.front(); q.pop(); vis[temp] = 0; tot[temp]++; if(tot[temp]>n){ flag = 1; break; } for(i=head[temp];i!=-1;i=edge[i].next){ int jz = edge[i].v; if(jz+dist[temp]<dist[edge[i].u]){ dist[edge[i].u] = jz + dist[temp]; if(!vis[edge[i].u]){ vis[edge[i].u] = 1; q.push(edge[i].u); } } } } } int main(){ int t,i,a,b,c; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&w); memset(head,-1,sizeof(head)); memset(tot,0,sizeof(tot)); cnt = 0; flag = 0; while(!q.empty()) q.pop(); for(i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&c); add_edge(a,b,c); add_edge(b,a,c); } for(i=0;i<w;i++){ scanf("%d%d%d",&a,&b,&c); add_edge(a,b,-c); } spfa(); if(flag) puts("YES"); else puts("NO"); } return 0; }
POJ--3259--Wormholes【SPFA判负权值回路】,布布扣,bubuko.com
时间: 2024-11-07 11:28:45