题目分析:
由于这题专卡
S
P
F
A
SPFA
S P F A ,已死 。 考虑到负权边,两点之间只有一条,故将双向边建图后,维护处连通块缩点,在建负权边,图为
D
A
G
DAG
D A G 在缩点图上跑拓扑排序,连通块内部跑
D
i
j
k
s
t
r
a
Dijkstra
D i j k s t r a ,就能维护处最短路
d
[
i
]
d[i]
d [ i ] 巨坑细节:
d
[
i
]
d[i]
d [ i ] 要初始化为
0
x
7
f
0x7f
0 x 7 f ,而当
d
[
i
]
>
0
x
3
f
d[i]>0x3f
d [ i ] > 0 x 3 f 的时候就不能到达了,为什么不是
d
[
i
]
=
=
0
x
7
f
d[i]==0x7f
d [ i ] = = 0 x 7 f 才不能到达呢?因为有可能一个点
d
[
u
]
=
0
x
7
f
d[u]=0x7f
d [ u ] = 0 x 7 f ,此时有一条边权为负,就可以去更新
d
[
v
]
d[v]
d [ v ] ,但
u
u
u 点都不能到达,
v
v
v 点肯定不能到达!!!!!!!!!!!
Code:
#include <bits/stdc++.h>
using namespace std;
#define maxn 25010
#define maxm_1 50010
#define maxm_2 50010
#define INF 0x3f3f3f3f
int d[ maxn] , st[ maxn] , top= 0 , size= 0 , vis[ maxn] , n, m_1, m_2, du[ maxn] , s, co[ maxn] , head[ maxn] ;
struct edge {
int v, w, nxt;
} e[ ( maxm_1<< 1 ) + maxm_2] ;
struct hepnode {
int pos, dis;
bool operator < ( const hepnode& rhs ) const {
return dis> rhs. dis;
}
} ;
inline void init_ ( ) {
freopen ( "a.txt" , "r" , stdin ) ;
freopen ( "abc.txt" , "w" , stdout ) ;
}
inline int read_ ( ) {
int 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<< 3 ) + ( x<< 1 ) + c- '0' ;
c= getchar ( ) ;
}
return x* f;
}
inline void clean_ ( ) {
memset ( head, - 1 , sizeof ( head) ) ;
memset ( co, 0 , sizeof ( co) ) ;
memset ( vis, 0 , sizeof ( vis) ) ;
memset ( du, 0 , sizeof ( du) ) ;
memset ( d, 0x7f , sizeof ( d) ) ;
}
inline void add_ ( int u, int v, int w) {
e[ ++ size] . v= v;
e[ size] . w= w;
e[ size] . nxt= head[ u] ;
head[ u] = size;
}
void dfs_ ( int u) {
co[ u] = co[ 0 ] ;
for ( int i= head[ u] ; ~ i; i= e[ i] . nxt) {
int v= e[ i] . v;
if ( ! co[ v] ) dfs_ ( v) ;
}
}
inline void topu_Dijkstra_ ( ) {
priority_queue< hepnode> q;
d[ s] = 0 ;
int t= 0 ;
while ( t< top) {
int col= st[ ++ t] ;
for ( int i= 1 ; i<= n; ++ i) {
if ( co[ i] == col) q. push ( ( hepnode) { i, d[ i] } ) ;
}
while ( ! q. empty ( ) ) {
hepnode pdc= q. top ( ) ;
q. pop ( ) ;
int u= pdc. pos;
if ( vis[ u] ) continue ;
vis[ u] = 1 ;
for ( int i= head[ u] ; ~ i; i= e[ i] . nxt) {
int v= e[ i] . v, w= e[ i] . w;
if ( d[ v] > d[ u] + w) {
d[ v] = d[ u] + w;
if ( co[ v] == co[ u] ) q. push ( ( hepnode) { v, d[ v] } ) ;
}
if ( co[ u] != co[ v] && ! -- du[ co[ v] ] ) st[ ++ top] = co[ v] ;
}
}
}
for ( int i= 1 ; i<= n; ++ i) {
if ( d[ i] > INF) puts ( "NO PATH" ) ;
else printf ( "%d\n" , d[ i] ) ;
}
}
void readda_ ( ) {
n= read_ ( ) ; m_1= read_ ( ) ; m_2= read_ ( ) ; s= read_ ( ) ;
clean_ ( ) ;
int x, y, z;
for ( int i= 1 ; i<= m_1; ++ i) {
x= read_ ( ) ; y= read_ ( ) ; z= read_ ( ) ;
add_ ( x, y, z) ; add_ ( y, x, z) ;
}
for ( int i= 1 ; i<= n; ++ i) {
if ( ! co[ i] ) {
++ co[ 0 ] ;
dfs_ ( i) ;
}
}
for ( int i= 1 ; i<= m_2; ++ i) {
x= read_ ( ) ; y= read_ ( ) ; z= read_ ( ) ;
add_ ( x, y, z) ;
++ du[ co[ y] ] ;
}
st[ ++ top] = co[ s] ;
for ( int i= 1 ; i<= co[ 0 ] ; ++ i) {
if ( ! du[ i] ) {
st[ ++ top] = i;
}
}
topu_Dijkstra_ ( ) ;
}
int main ( ) {
init_ ( ) ;
readda_ ( ) ;
return 0 ;
}