Vijos——T1053 Easy sssp

https://vijos.org/p/1053

描述

输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 
要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一个点沿着某条路径出发, 又回到了自己, 而且所经过的边上的权和小于0, 就说这条路是一个负权回路.
如果存在负权回路, 只输出一行-1;
如果不存在负权回路, 再求出一个点S(1 <= S <= N)到每个点的最短路的长度. 约定: S到S的距离为0, 如果S与这个点不连通, 则输出NoPath.

格式

输入格式

第一行: 点数N(2 <= N <= 1,000), 边数M(M <= 100,000), 源点S(1 <= S <= N);
以下M行, 每行三个整数a, b, c表示点a, b(1 <= a, b <= N)之间连有一条边, 权值为c(-1,000,000 <= c <= 1,000,000)

输出格式

如果存在负权环, 只输出一行-1, 否则按以下格式输出
共N行, 第i行描述S点到点i的最短路: 
如果S与i不连通, 输出NoPath;
如果i = S, 输出0;
其他情况输出S到i的最短路的长度.

样例1

样例输入1

6 8 1
1 3 4
1 2 6
3 4 -7
6 4 2
2 4 5
3 6 3
4 5 1
3 5 4

样例输出1

0
6
4
-3
-2
7

限制

Test5 5秒
其余 1秒

提示

 无聊的题,通过率我见过最低的题

很多坑,可能是不连通图

第一次T了,因为傻傻的跑了N次求最短路的SPFA ,

然后又W了,被WHW学长坑了~~~

之后就——》》比较喜欢用DFS判负环—     可以将两个SPFA和在一起但是太麻烦 懒得改了~~~

  1 #include <algorithm>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5 
  6 using namespace std;
  7 
  8 const int M(100000+15);
  9 const int N(1000+15);
 10 const int INF(1e8);
 11 int n,m,s,u,v,w;
 12 
 13 int head[M],sumedge;
 14 struct Edge
 15 {
 16     int v,w,next;
 17     Edge(int v=0,int next=0,int w=0):
 18         v(v),next(next),w(w) {}
 19 }edge[M];
 20 void ins(int u,int v,int w)
 21 {
 22     edge[++sumedge]=Edge(v,head[u],w);
 23     head[u]=sumedge;
 24 }
 25 
 26 long long dis[N];
 27 int if_ring,vis[N];
 28 void SPFAring(int pre)
 29 {
 30     if(if_ring) return ;
 31     vis[pre]=1;
 32     for(int i=head[pre];i;i=edge[i].next)
 33     {
 34         int to=edge[i].v;
 35         if(dis[to]>dis[pre]+edge[i].w)
 36         {
 37             if(vis[to]||if_ring)
 38             {
 39                 if_ring=1;
 40                 break ;
 41             }
 42             dis[to]=dis[pre]+edge[i].w;
 43             SPFAring(to);
 44         }
 45     }
 46     vis[pre]=0;
 47 }
 48 
 49 void SPFAdist(int s)
 50 {
 51     queue<int>que;
 52     que.push(s);
 53     vis[s]=1;
 54     dis[s]=0;
 55     while(!que.empty())
 56     {
 57         u=que.front();que.pop();vis[u]=0;
 58         for(int i=head[u];i;i=edge[i].next)
 59         {
 60             v=edge[i].v;
 61             if(dis[v]>dis[u]+edge[i].w)
 62             {
 63                 dis[v]=dis[u]+edge[i].w;
 64                 if(!vis[v]) que.push(v),vis[v]=1;
 65             }
 66         }
 67     }
 68 }
 69 
 70 int if_,ch;
 71 void read(int &x)
 72 {
 73     x=0;if_=0;ch=getchar();
 74     for(;ch>'9'||ch<'0';ch=getchar())
 75         if(ch=='-') if_=1;
 76     for(;ch<='9'&&ch>='0';ch=getchar())
 77         x=x*10+ch-'0';
 78     if(if_) x=(~x)+1;
 79 }
 80 
 81 int main()
 82 {
 83     read(n);read(m);read(s);
 84     for(;m;m--)
 85     {
 86         read(u);read(v);read(w);
 87         ins(u,v,w);
 88     }
 89     for(int i=1;i<=n;i++)
 90     {
 91         SPFAring(i);
 92         if(if_ring)
 93         {
 94             printf("-1
");
 95             return 0;
 96         }
 97     }
 98     for(int j=1;j<=n;j++)
 99     {
100         dis[j]=INF;
101         vis[j]=0;
102     }
103     SPFAdist(s);
104     for(int i=1;i<=n;i++)
105     {        
106         if(i==s)
107         {
108             printf("0
");
109             continue;
110         }
111         if(dis[i]>=INF) printf("NoPath
");
112         else printf("%lld
",dis[i]);
113     }
114     return 0;
115 }
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
原文地址:https://www.cnblogs.com/Shy-key/p/6963239.html