spfa + slf优化


最近在练习费用流 , 不是要用spfa吗 ,我们教练说:ns学生写朴素的spfa说出去都让人笑 。

QwQ,所以就去学了一下优化 。

slf优化就是双向队列优化一下,本来想用lll优化,可是优化后我tm居然t了(那道题特地卡spfa),所以lll优化太迷了 ,还是只用slf优化好 。

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <deque>
 6 const int inf = 1 << 30 , maxn = 100000 + 11 , M = 200000 + 11  ; 
 7 using namespace std ;//1061109567
 8 int n , m , head[maxn]  , dis[maxn] , cnt , sum , tot ;
 9 bool mark[maxn] ; 
10 struct id
11 {
12     int nxt ,to , val ;
13 } edge[M] ;
14 deque < int > Q ;
15 
16 
17 inline void Init ( )
18 {
19     freopen( "NSOOJ#10719.in" , "r" , stdin  ) ;
20     freopen( "NSOOJ#10719.out" , "w" , stdout ) ;
21 }
22 
23 int read( )
24 {
25     char ch = getchar( ) ; int k = 1 , ret = 0 ;
26     while( ch < '0' || ch > '9' ) { if( ch == '-' ) k = -1 ; ch = getchar( ) ; }
27     while( ch >= '0' && ch <= '9' ) ret = ret * 10 + ch - '0' , ch = getchar( ) ;
28     return k * ret ;
29 }
30 
31 void add( int u , int v , int va )
32 {
33     edge[++cnt].nxt = head[u] , edge[cnt].to = v ;
34     edge[cnt].val = va , head[u] = cnt ;
35 }
36 
37 void input(  )
38 {
39     n = read()  , m = read( ) ;
40     int u ,v , c ;
41     memset( head , -1 , sizeof(head)) ;
42     for( int x = 1 ; x <= m ; ++x )
43     {
44         u = read( ) , v = read( ) , c = read( ) ;
45         add( u ,v , c )  ;
46     }
47 }
48 
49 void spfa( )
50 {
51     memset( dis , 127/2 , sizeof(dis) ) ;
52     dis[1] = 0 , mark[1] = true ;
53     Q.push_back( 1 ) ;
54     while( !Q.empty( ) )
55     {
56         int u = Q.front( ) ; Q.pop_front( ) ; mark[u] = false ;
57     
58         for( int i = head[u] ; ~i ; i = edge[i].nxt )
59         {
60             int v = edge[i].to ; 
61             if( dis[v] > dis[u] + edge[i].val )
62             {
63                 dis[v] = dis[u] + edge[i].val ;
64                 if( !mark[v] )
65                 {
66                     mark[v] = true ; 
67                     if( Q.empty( ) || dis[v] > dis[Q.front( )]  ) Q.push_back( v ) ;
68                     else Q.push_front( v ) ;
69                     
70                 }
71             
72             }
73         }
74     }
75     if( dis[n] == 1061109567 ) printf( "%d\n" , -1 ) ;
76     else printf( "%d\n" , dis[n] ) ;
77 }
78 
79 
80 int main( )
81 {
82 //    Init( ) ; 
83     input( ) ;
84     spfa( ) ;
85 //    fclose( stdin ) ;
86 //       fclose( stdout ) ;
87     return 0 ;
88 }

 纠正,其实lll优化一般效率还是挺高的,只是学长说如果要卡的话可以卡到指数级(=_=),所以下面是lll优化的代码 。 

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <deque>
 6 const int inf = 1 << 30 , maxn = 100000 + 11 , M = 200000 + 11  ; 
 7 using namespace std ;//1061109567
 8 int n , m , head[maxn]  , dis[maxn] , cnt , sum , tot ;
 9 bool mark[maxn] ; 
10 struct id
11 {
12     int nxt ,to , val ;
13 } edge[M] ;
14 deque < int > Q ;
15 
16 
17 inline void Init ( )
18 
19 {
20     freopen( "NSOOJ#10719.in" , "r" , stdin  ) ;
21     freopen( "NSOOJ#10719.out" , "w" , stdout ) ;
22 }
23 
24 int read( )
25 {
26     char ch = getchar( ) ; int k = 1 , ret = 0 ;
27     while( ch < '0' || ch > '9' ) { if( ch == '-' ) k = -1 ; ch = getchar( ) ; }
28     while( ch >= '0' && ch <= '9' ) ret = ret * 10 + ch - '0' , ch = getchar( ) ;
29     return k * ret ;
30 }
31 
32 void add( int u , int v , int va )
33 {
34     edge[++cnt].nxt = head[u] , edge[cnt].to = v ;
35     edge[cnt].val = va , head[u] = cnt ;
36 }
37 
38 void input(  )
39 {
40     n = read()  , m = read( ) ;
41     int u ,v , c ;
42     memset( head , -1 , sizeof(head)) ;
43     for( int x = 1 ; x <= m ; ++x )
44     {
45         u = read( ) , v = read( ) , c = read( ) ;
46         add( u ,v , c )  ;
47     }
48 }
49 
50 void spfa( )
51 {
52     memset( dis , 127/2 , sizeof(dis) ) ;
53     dis[1] = 0 , mark[1] = true ;
54     Q.push_back( 1 ) ; tot = 0 ;
55     while( !Q.empty( ) )
56     {
57         int u = Q.front( ) ; Q.pop_front( ) ; mark[u] = false ;
58         tot-- ; sum -= dis[u] ;
59         for( int i = head[u] ; ~i ; i = edge[i].nxt )
60         {
61             int v = edge[i].to ; 
62             if( dis[v] > dis[u] + edge[i].val )
63             {
64                 dis[v] = dis[u] + edge[i].val ;
65                 if( !mark[v] )
66                 {
67                     mark[v] = true ; 
68                     if( Q.empty( ) || dis[v] * tot <= sum ) Q.push_back( v ) ;
69                     else Q.push_front( v ) ;
70                     tot++ ; sum += dis[v] ;
71                 }
72             
73             }
74         }
75     }
76     if( dis[n] == 1061109567 ) printf( "%d\n" , -1 ) ;
77     else printf( "%d\n" , dis[n] ) ;
78 }
79 
80 
81 int main( )
82 {
83 //    Init( ) ; 
84     input( ) ;
85     spfa( ) ;
86 //    fclose( stdin ) ;
87 //       fclose( stdout ) ;
88     return 0 ;
89 }

好的,下面是两个都加的代码 。

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <deque>
 6 const int inf = 1 << 30 , maxn = 100000 + 11 , M = 200000 + 11  ; 
 7 using namespace std ;//1061109567
 8 int n , m , head[maxn]  , dis[maxn] , cnt , sum , tot ;
 9 bool mark[maxn] ; 
10 struct id
11 {
12     int nxt ,to , val ;
13 } edge[M] ;
14 deque < int > Q ;
15 
16 
17 inline void Init ( )
18 {
19     freopen( "NSOOJ#10719.in" , "r" , stdin  ) ;
20     freopen( "NSOOJ#10719.out" , "w" , stdout ) ;
21 }
22 
23 int read( )
24 {
25     char ch = getchar( ) ; int k = 1 , ret = 0 ;
26     while( ch < '0' || ch > '9' ) { if( ch == '-' ) k = -1 ; ch = getchar( ) ; }
27     while( ch >= '0' && ch <= '9' ) ret = ret * 10 + ch - '0' , ch = getchar( ) ;
28     return k * ret ;
29 }
30 
31 void add( int u , int v , int va )
32 {
33     edge[++cnt].nxt = head[u] , edge[cnt].to = v ;
34     edge[cnt].val = va , head[u] = cnt ;
35 }
36 
37 void input(  )
38 {
39     n = read()  , m = read( ) ;
40     int u ,v , c ;
41     memset( head , -1 , sizeof(head)) ;
42     for( int x = 1 ; x <= m ; ++x )
43     {
44         u = read( ) , v = read( ) , c = read( ) ;
45         add( u ,v , c )  ;
46     }
47 }
48 
49 void spfa( )
50 {
51     memset( dis , 127/2 , sizeof(dis) ) ;
52     dis[1] = 0 , mark[1] = true ;
53     Q.push_back( 1 ) ; tot = 1 ;
54     while( !Q.empty( ) )
55     {
56         int u = Q.front( ) ; Q.pop_front( ) ; mark[u] = false ;
57         tot-- ; sum -= dis[u] ;
58         for( int i = head[u] ; ~i ; i = edge[i].nxt )
59         {
60             int v = edge[i].to ; 
61             if( dis[v] > dis[u] + edge[i].val )
62             {
63                 dis[v] = dis[u] + edge[i].val ;
64                 if( !mark[v] )
65                 {
66                     mark[v] = true ; 
67                     if( Q.empty( ) || dis[v] > dis[Q.front( )] || dis[v] * tot <= sum ) Q.push_back( v ) ;
68                     else Q.push_front( v ) ;
69                     tot++ ; sum += dis[v] ;
70                 }
71             
72             }
73         }
74     }
75     if( dis[n] == 1061109567 ) printf( "%d\n" , -1 ) ;
76     else printf( "%d\n" , dis[n] ) ;
77 }
78 
79 
80 int main( )
81 {
82 //    Init( ) ; 
83     input( ) ;
84     spfa( ) ;
85 //    fclose( stdin ) ;
86 //       fclose( stdout ) ;
87     return 0 ;
88 }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM