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的最短路的长度.
限制
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; }