vijos 1053Easy sssp

P1053Easy sssp
 
 

描述

输入数据给出一个有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秒

提示

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

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#define N 1010
#define M 100010
#define inf 9999999999999LL
#define LL long long
using namespace std;
int head[N],in[N],n,m,s;
LL dist[N],dis1[N];
struct node{
    int v,next;
    long long w;
}e[M];
bool flag,vis[N],use[N];
void add(int cnt,int x,int y,int z){
    e[cnt].v=y;
    e[cnt].w=z;
    e[cnt].next=head[x];
    head[x]=cnt;
}
void spfa(int so,LL dis[]){
    queue<int>que;
    dis[so]=0;
    vis[so]=1;
    use[so]=1;
    in[so]++;
    que.push(so);
    while(!que.empty()){
        int u=que.front();que.pop();
        vis[u]=0;
        for(int i=head[u];i;i=e[i].next){
            if(dis[e[i].v]>dis[u]+e[i].w){
                dis[e[i].v]=dis[u]+e[i].w;
                if(!vis[e[i].v]){
                    vis[e[i].v]=1;
                    use[e[i].v]=1;
                    que.push(e[i].v);
                    if(++in[e[i].v]>=n||dis[so]<0){
                        flag=1;
                        return ;
                    }
                }
                    
            }
        }
    }
}
int main(){
    //freopen("sh.txt","r",stdin);
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=m;i++){
        int x,y;LL z;
        scanf("%d%d%lld",&x,&y,&z);
        add(i,x,y,z);
    }
    fill(dist,dist+n+1,inf);
    for(int i=1;i<=n;i++){
        if(use[i]) continue;
        if(flag){
            puts("-1");return 0;
        }
        spfa(i,dis1);
    }
    spfa(s,dist);
    if(flag){
        puts("-1");return 0;
    }
    for(int i=1;i<=n;i++){
        if(dist[i]<inf)
            cout<<dist[i]<<endl;
        else
            printf("NoPath
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shenben/p/5742816.html