题目描述
给出一张图,如果存在负环就输出-1,否则就求出s到每个点的最短路径。
思路
众所周知,我们可以用spfa求最短路是顺便判断是否存在环,不过这里用spfa判环绝对会被卡爆了。不过我们考虑dfs求是否存在环,如果存在环直接输出-1,不存在再跑一遍spfa求最短路即可。
代码
#include <bits/stdc++.h> using namespace std; const int N=1100,M=1e5+10; int nxt[M],to[M],w[M],head[N],tot; int dis[N],vis[N],f,mine; bool exist[N]; int read() { int res=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();} return res*w; } void clear() { memset(dis,0,sizeof(dis)); memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); tot=0;f=0; } void add_edge(int x,int y,int v) { nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; w[tot]=v; } void spfa_dfs(int u,int st) { if(f)return ; vis[u]=st; for(int i=head[u];~i;i=nxt[i]) { int v=to[i]; if(dis[v]>dis[u]+w[i]) { dis[v]=dis[u]+w[i]; if(dis[v]<mine){f=1;return ;} if(!vis[v])spfa_dfs(v,st); if(vis[v]==st) { if(dis[v]<0)f=1; return ; } } } vis[u]=0; } void spfa_bfs(int s) { queue<int>q; memset(dis,0x3f,sizeof(dis)); dis[s]=0;q.push(s);exist[s]=1; while(!q.empty()) { int u=q.front();q.pop(); exist[u]=0; for(int i=head[u];~i;i=nxt[i]) { int v=to[i]; if(dis[v]>dis[u]+w[i]) { dis[v]=dis[u]+w[i]; if(!exist[v]) { exist[v]=1; q.push(v); } } } } } int main() { // freopen("aa.txt","r",stdin); int n,m,s; mine=10000000; clear(); n=read();m=read();s=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(),z=read(); add_edge(x,y,z); mine=min(mine,z); } mine=mine*n; for(int i=1;i<=n;i++) { spfa_dfs(i,i); //求负环 if(f)break ; } if(f)printf("-1"); else { spfa_bfs(s); //求最短路 for(int i=1;i<=n;i++) if(dis[i]==0x3f3f3f3f)printf("NoPath\n"); else printf("%d\n",dis[i]); } return 0; }