Easy sssp

来源:互联网 发布:富贵鸡源码 编辑:程序博客网 时间:2024/05/16 23:55

描述

输入数据给出一个有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 11 3 41 2 63 4 -76 4 22 4 53 6 34 5 13 5 4
Copy

样例输出1

064-3-27
Copy

限制

Test5 5秒
其余 1秒

提示

做这道题时, 你不必为超时担心, 不必为不会算法担心, 但是如此“简单”的题目, 你究竟能ac么?


【题解】

感觉vijos的题目质量比luogu好啊。

注意溢出,答案要用long long

写图论题的时候要千万注意,是否是连通图连通图连通图连通图连通图连通图连通图连通图连通图连通图连通图连通图

原理就是SPFA判断负环以及求最短路。加入了读入优化,但感觉vijos的时间统计有点low每次递交显示的time都不一样。

#include<cstdio>#include<vector>#include<queue>#include<cstring>using namespace std;#define INF 0x3f3f3f3fconst int maxn=1010;struct Edge{int from,to,dist;Edge(int u,int v,int d):from(u),to(v),dist(d){}};vector<int>G[maxn];vector<Edge>edges;int n,m;void Init(){for(int i=1;i<=n;i++)G[i].clear();edges.clear();}void AddEdge(int from,int to,int dist){edges.push_back(Edge(from,to,dist));G[from].push_back(edges.size()-1);}inline int read(){int X=0,W=1;char ch=0;while(ch>'9'||ch<'0'){if(ch=='-')W=-1;ch=getchar();}while(ch>='0'&&ch<='9')X=(X<<3)+(X<<1)+ch-'0',ch=getchar();return X*W;}inline void write(long long  X){if(X<0)putchar('-'),X=-X;if(X>9)write(X/10);putchar(X%10+'0');}bool vis[maxn]={0};long long d[maxn],ans[maxn];bool SPFA(int s){int cnt[maxn]={0};bool inq[maxn]={0};for(int i=1;i<=n;i++)d[i]=INF;queue<int>Q;Q.push(s);d[s]=0;while(!Q.empty()){int x=Q.front();Q.pop();inq[x]=false;for(int i=0;i<G[x].size();i++){Edge &e=edges[G[x][i]];if(d[e.to]>d[x]+e.dist){d[e.to]=d[x]+e.dist;if(inq[e.to]==0){Q.push(e.to);inq[e.to]=true;}if(++cnt[e.to]>n)return false;}}}for(int i=1;i<=n;i++)vis[i]=vis[i]||cnt[i];return true;}int main(){int s;n=read(),m=read(),s=read();Init();int from,to,dist;for(int i=1;i<=m;i++){from=read(),to=read(),dist=read();AddEdge(from,to,dist);}SPFA(s);for(int i=1;i<=n;i++)ans[i]=d[i];for(int i=1;i<=n;i++)if(vis[i]==0)if(SPFA(i)==0){puts("-1");return 0;}for(int i=1;i<=n;i++){if(ans[i]==INF)puts("NoPath");else{write(ans[i]);putchar('\n');}}return 0;}















原创粉丝点击