Vijos 1053 easy 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么?

/*
SPFA的裸题
但要注意两个问题
1.给的起点可能到不了图中存在的负环
2.int不够用,要用long long
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#define maxn 100010
#define maxx 1010
#define ll long long
using namespace std;
ll n,m,s,topt,a[maxx],first[maxx],dis[maxx],f[maxx],dis1[maxx];
queue<ll>q;
struct edge
{
    ll from;
    ll to;
    ll val;
    ll next;
}e[maxn];
ll init()
{
    ll x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
void add(ll x,ll y,ll z)
{
    topt++;
    e[topt].from=x;
    e[topt].to=y;
    e[topt].val=z;
    e[topt].next=first[x];
    first[x]=topt;
}
void SPFA(ll x)
{
    memset(dis,127/3,sizeof(dis));
    memset(f,0,sizeof(f));
    q.push(x);
    dis[x]=0;
    f[x]=1;
    a[x]++;
    while(!q.empty())
    {
        ll u=q.front();
        q.pop();
        f[u]=0;
        for(ll i=first[u];i;i=e[i].next)
        {
            ll t=e[i].to;
            if(dis[t]>dis[u]+e[i].val)
            {
                dis[t]=dis[u]+e[i].val;
                if(!f[t])
                {
                    q.push(t);
                    a[t]++;
                    if(a[t]>n)
                    {
                        printf("-1\n");
                        exit(0);
                    }
                    f[t]=1;
                }
            }
        }
    }
}
void spfa(ll x)
{
    memset(dis1,127/3,sizeof(dis1));
    memset(f,0,sizeof(f));
    memset(a,0,sizeof(a));
    q.push(x);
    dis1[x]=0;
    f[x]=1;
    a[x]++;
    while(!q.empty())
    {
        ll u=q.front();
        q.pop();
        f[u]=0;
        for(ll i=first[u];i;i=e[i].next)
        {
            ll t=e[i].to;
            if(dis1[t]>dis1[u]+e[i].val)
            {
                dis1[t]=dis1[u]+e[i].val;
                if(!f[t])
                {
                    q.push(t);
                    a[t]++;
                    if(a[t]>n)
                    {
                        printf("-1\n");
                        exit(0);
                    }
                    f[t]=1;
                }
            }
        }
    }
}
int main()
{
    ll i,j,k;
    n=init();m=init();s=init();
    for(i=1;i<=m;i++)
    {
        ll x,y,z;
        x=init();y=init();z=init();
        add(x,y,z);
    }
    SPFA(s);
    for(i=1;i<=n;i++)
    if(dis[i]==dis[0])
    spfa(i);
    for(i=1;i<=n;i++)
    {
        if(dis[i]>=dis[0])
        printf("NoPath\n");
        else
        printf("%lld\n",dis[i]);
    }
    return 0;
}

 

 
posted @ 2016-08-05 17:28  岂是蓬蒿人  阅读(138)  评论(0编辑  收藏  举报