好久不写spfa了 但在纸上写写 还是可以敲出来 它的思想还是还是很简单 这里就不介绍了 掌握spfa真的很好 除非题目的数据故意卡spfa...那就只能用dij去做了或者floyd
这题 相比一般我们去求 最短路 有稍许不同 但是你只要明白了spfa的思想 就是进行下转换就可以了
又是打印路径 好多题遇到了啊.. 我还是喜欢用stack去打印 虽然这样会显得多一步for的入栈 但这样只有O(n) 如果tle 肯定也与此无关吧-
这里 我的建图 就是一般的使用struct的邻接表 本来想写下 前向星的 发现对于head数组 有点生疏了 就不写了 还是我现在写的这个容易理解 你可以将它看成自己模拟了个vector来实现 很像的
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <stack> 5 using namespace std; 6 7 int n; 8 const int size = 110; 9 struct graph 10 { 11 int num; 12 int next[size-10]; 13 }node[size]; 14 int val[size]; 15 int sum[size]; 16 int path[size]; 17 bool vis[size]; 18 queue<int>q; 19 stack<int>s; 20 21 void init( ) 22 { 23 while( !q.empty() ) 24 q.pop(); 25 for( int i = 0 ; i<size-5 ; i++ ) 26 node[i].num = 0; 27 memset( vis , false , sizeof(vis) ); 28 memset( sum , 0 , sizeof(sum) ); 29 memset( path , -1 , sizeof(path) ); 30 } 31 32 void spfa( ) 33 { 34 int now , point; 35 q.push(1); 36 vis[1] = true; 37 while( !q.empty() ) 38 { 39 now = q.front(); 40 q.pop(); 41 for( int i = 0 ; i<node[now].num ; i++ ) 42 { 43 point = node[now].next[i]; 44 if( sum[now] + val[point] >= sum[point] ) 45 { 46 sum[point] = sum[now] + val[point]; 47 path[point] = now; 48 if( !vis[point] ) 49 { 50 vis[point] = true; 51 q.push(point); 52 } 53 } 54 } 55 vis[now] = false; 56 } 57 } 58 59 void output( ) 60 { 61 s.push( n+1 ); 62 for( int i = path[n+1] ; i!=-1 ; i=path[i] ) 63 { 64 s.push( i ); 65 } 66 while( !s.empty( ) ) 67 { 68 if( s.top() == n+1 ) 69 { 70 cout << 1; 71 } 72 else 73 { 74 cout << s.top( ) << "->"; 75 } 76 s.pop(); 77 } 78 cout << endl; 79 } 80 81 int main() 82 { 83 int t , m , cnt , x , y , num; 84 while( cin >> t ) 85 { 86 cnt = 1; 87 for( int k = 1 ; k<=t ; k++ ) 88 { 89 init(); 90 cin >> n; // n+1个结点 91 for( int i = 1 ; i<=n ; i++ ) 92 { 93 cin >> val[i]; 94 } 95 val[n+1] = 0; 96 cin >> m; 97 while( m-- ) // m对关系 98 { 99 cin >> x >> y; 100 num = node[x].num; 101 node[x].next[ node[x].num++ ] = y; 102 } 103 spfa(); 104 cout << "CASE " << cnt++ << "#" << endl; 105 cout << "points " << ": " << sum[n+1] << endl; 106 cout << "circuit : "; 107 output( ); 108 if(k<t) 109 cout << endl; 110 } 111 } 112 return 0; 113 }
这几天 正好不出去玩 看了好多部电影--推荐几部--意外 -古天乐 单身男女--古天乐 窃听风云 1 2 3 大概就看了这5部吧
写完这个去看下 孤男寡女--刘德华 然后晚上来写下它的dp版本=-=
这个的dp真的狠简单 我都觉得和我写的spfa没有太大区别 就是spfa弄了个队列优化的感觉....
它的状态方程dp[ j ] = max( dp[ j ] , dp[ i ] + val[ j ] )就是对应我spfa里以前所谓的 松弛 操作... 写起来很快 所以
1 #include <iostream> 2 #include <cstring> 3 #include <stack> 4 using namespace std; 5 6 int n; 7 const int size = 110; 8 bool mp[size][size]; 9 int path[size]; 10 int val[size]; 11 int dp[size]; 12 stack<int>s; 13 14 void init() 15 { 16 memset( dp , 0 , sizeof(dp) ); 17 memset( mp , false , sizeof(mp) ); 18 memset( path , -1 , sizeof(path) ); 19 } 20 21 void solve( ) 22 { 23 for( int i = 1 ; i<=n ; i++ ) 24 { 25 for( int j = i+1 ; j<=n+1 ; j++ ) 26 { 27 if( mp[i][j] ) 28 { 29 if( dp[j] <= dp[i] + val[j] ) 30 { 31 path[j] = i; 32 dp[j] = dp[i] + val[j]; 33 } 34 } 35 } 36 } 37 } 38 39 void output( ) 40 { 41 s.push( n+1 ); 42 for( int i = path[n+1] ; i!=-1 ; i = path[i] ) 43 { 44 s.push( i ); 45 } 46 while( !s.empty() ) 47 { 48 if( s.top() == n+1 ) 49 { 50 cout << 1 << endl; 51 } 52 else 53 { 54 cout << s.top( ) << "->"; 55 } 56 s.pop(); 57 } 58 } 59 60 int main() 61 { 62 int t , m , x, y; 63 while( cin >> t ) 64 { 65 for( int k = 1 ; k<=t ; k++ ) 66 { 67 init( ); 68 cin >> n; 69 for( int i = 1 ; i<=n ; i++ ) 70 { 71 cin >> val[i]; 72 } 73 val[n+1] = 0; 74 cin >> m; 75 while( m-- ) 76 { 77 cin >> x >> y; 78 mp[x][y] = true; 79 } 80 solve( ); 81 cout << "CASE " << k << "#" << endl; 82 cout << "points " << ": " << dp[n+1] << endl; 83 cout << "circuit : "; 84 output( ); 85 if(k<t) 86 cout << endl; 87 } 88 } 89 return 0; 90 }
today:
我这一生遇到过很多人 他们如同指间的烟火 忽明忽暗 最后只沦为一抹灰烬
而你不同 你如北斗 闪耀在我的整个人生