Easy SSSP

https://loj.ac/problem/10086

题目描述

  给出一张图,如果存在负环就输出-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;
}

猜你喜欢

转载自www.cnblogs.com/fangbozhen/p/11708842.html