VIJOS 1053 Easy sssp 负权最短路

题目大意:

中文题。


解题思路:

带负权的最短路,记录一下每个点入队次数,入队两次即说明存在负环。


#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#define LL long long
#define db double
#define maxnn 10000000
#define EPS 1e-15

#define inf 1000000000
#define pa pair<int,int>
using namespace std;
const int maxn=101000;
int n,m,k,t,x,y,s,z,tot=0;
struct edge{
    int to,w,next;
}e[1010000];
int head[maxn],dist[maxn],ans[maxn];
bool vis[maxn];
int f[maxn];
bool flag;
void add(int x,int y,int z){
    e[tot].to=y;
    e[tot].w=z;
    e[tot].next=head[x];
    head[x]=tot++;
}
bool spfa(int s){
	queue<int>q;
	memset(dist,63,sizeof(dist));
	memset(vis,false,sizeof(vis));
	memset(ans,0,sizeof(ans));
	q.push(s);
	dist[s]=0;
	while(!q.empty()){
		int u=q.front(); q.pop();
		vis[u]=false;
		for (int i=head[u];i!=-1;i=e[i].next){
			if (dist[e[i].to]>dist[u]+e[i].w){
				dist[e[i].to]=dist[u]+e[i].w;
				if (!vis[e[i].to]){
					vis[e[i].to]=1;
					int v=e[i].to;
					q.push(v);
					if (ans[v]<2) {ans[v]++;}
					else return true;
				}
			}
		}
	}
	return false;
}
int main(){
    scanf("%d%d%d",&n,&m,&s);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        if(x==y && z<0){
            printf("-1\n");
            return 0;
        }
    }
    for(int i=1;i<=n;i++){
        if(spfa(i)){
            printf("-1\n");
            return 0;
        }
    }
    spfa(s);
    for(int i=1;i<=n;i++){
        if(dist[i]>1000000){
            if(i!=s) printf("NoPath\n");
            else printf("0\n");
        }
        else printf("%d\n",dist[i]);
    }
    return 0;
}


你可能感兴趣的:(VIJOS 1053 Easy sssp 负权最短路)