SPFA_YZOI 1662: Easy sssp, spfa_yzoisssp
Description
The input data is given a weighted directed graph with N (2 <= N <= 1,000) nodes and M (M <= 100,000) edges. you are required to write a program to determine whether a negative weight loop exists in the directed graph. if you start from a point along a path and return to yourself, and the right on the edge is less than 0, this path is a negative weight loop. if a negative weight loop exists, only one row-1 is output. If no negative weight loop exists, find another vertex S (1 <= S <= N) the shortest length to each point. convention: the distance from S to S is 0. If S is not connected to this vertex, NoPath is output.
Input
Row 1: number of points N (2 <= N <= 1,000), number of edges M (M <= 100,000), source point S (1 <= S <= N ); in the following M rows, each row has three integers a, B, and c, indicating that an edge is connected between vertex a and vertex B (1 <= a, B <= N, the weight is c (-1,000,000 <= c <= 1,000,000)
Output
If a negative weight ring exists, only one row-1 is output. Otherwise, N rows are output in the following format. line I describes the shortest path of point-to-point I. If S is not connected to I, output NoPath; if I = S, the output is 0; otherwise, the maximum short-circuit length from S to I is output.
This question is really an exception. The question is the surface of sssp, But it hides the spfa's heart at this moment (it seems impossible). The following describes the detailed operation steps of spfa (which should be similar to dijkstra ):
G [I] [j] indicates the adjacent matrix dist [I] indicates the distance from the source point to I. cnt [I] indicates the number of entry times of vertex I. v [I] indicates whether the vertex I is in queue in progress
Initialization: the value of the v [] array is false. cnt [] = 0, which changes the distance between all vertices and The Source Vertex to a large value.
Then, the source node is queued and the dist [start] is changed to 0.
Then we will perform operations similar to bfs to expand the shortest distance for updating the team's first point ......
If the number of queues at a certain point is greater than n, there must be a negative ring proof: if a point has a positive and short-circuited path, it can be connected to all other points at most and extended n times. If it is a negative ring, the shorter the point, the more smaller expansion, of course, more than n times.
Here, we also need to pay attention to the negative ring. Because this negative ring is not necessarily on the Source Path, should we retrieve all vertices? Obviously, there are not two ways to recommend the second method:
Use dfs to find connected blocks and then perform SPFA for each connected Block
Given the guidance of zbt, you can add an inbound value of 0. Only the outbound edge is connected to all vertices except him. Then, if you expand this vertex, you can find all the negative loops.
The last point is that in vijos, only 50 points of rough parts are estimated to be the problem of this adjacent matrix. It is best to change it to the number group of edge sets for code next time.
The Code is as follows:
#include<iostream>#include<cstdio>#include<queue>#include<algorithm>using namespace std;const int maxn=1000+10;long long g[maxn][maxn],dist[maxn],cnt[maxn];bool v[maxn],used[maxn];int n,m,s;int a,b,c;queue<int>q;bool SPFA(int start){ for(int i=1;i<=n;i++) { dist[i]=0x7f7f7f; cnt[i]=0; v[i]=false; } while(!q.empty()) q.pop(); v[start]=true; q.push(start); dist[start]=0; while(!q.empty()) { int x=q.front(); q.pop(); v[x]=false; for(int k=1;k<=n;k++) if(g[x][k]<0x7f7f7f&&dist[x]+g[x][k]<dist[k]) { dist[k]=dist[x]+g[x][k];// used[k]=true; if(!v[k]) { cnt[k]++; if(cnt[k]>n) return false; v[k]=true; q.push(k); } } } return true;}int main(){ ios::sync_with_stdio(false);// freopen("1.in","r",stdin); cin>>n>>m>>s; for(int i=1;i<=n+1;i++) for(int j=1;j<=n+1;j++) g[i][j]=0x7f7f7f; for(int i=1;i<=m;i++) { cin>>a>>b>>c; if(c<g[a][b]) g[a][b]=c; } for(int i=1;i<=n;i++) g[n+1][i]=1;// for(int i=1;i<=n;i++)// {// for(int j=1;j<=n;j++)// cout<<g[i][j]<<' ';// cout<<endl;// }// for(int i=1;i<=n;i++)// {// if(!SPFA(i))// {// cout<<-1<<endl;// return 0;// }// } if(!SPFA(n+1)) { cout<<-1<<endl; return false; } SPFA(s); for(int i=1;i<=n;i++) { if(dist[i]==0x7f7f7f) { cout<<"NoPath"<<endl; continue; } cout<<dist[i]<<endl; } return 0;}