又学了一遍差分约束系统
SPOJ 1451
NOI 1999的原题,
1 /*
2 * =====================================================================================
3 *
4 * Filename: SPFA.cpp
5 *
6 * Description: SPFA
7 *
8 * Version: 1.0
9 * Created: 2011年03月01日 18时11分01秒
10 * Revision: none
11 * Compiler: gcc
12 *
13 * Author: ronaflx
14 * Company: hit-acm-group
15 *
16 * =====================================================================================
17 */
18 #include < iostream >
19 #include < cstring >
20 #include < cstdio >
21 #include < queue >
22 using namespace std;
23 const int V = 1010 ;
24 const int E = 300001 ;
25 const int INF = 10000000 ;
26
27 struct edges
28 {
29 int v, val;
30 edges * next;
31 } pool[E], * g[V], * pp;
32 int cnt[V], dist[V], q[V];
33 bool vst[V];
34
35 void initialize()
36 {
37 memset(g, 0 , sizeof (g));
38 pp = pool;
39 }
40
41 void addedge( int a, int b, int v)
42 {
43 pp -> v = b;
44 pp -> val = v;
45 pp -> next = g[a];
46 g[a] = pp ++ ;
47 }
48
49 void SPFA( int n)
50 {
51 memset(cnt, 0 , sizeof (cnt));
52 memset(vst, false , sizeof (vst));
53 fill(dist, dist + n, INF);
54 dist[n - 1 ] = 0 ;
55 vst[n - 1 ] = true ;
56 int tail = 0 ;
57 q[ 0 ] = n - 1 ;
58 for ( int i = 0 ;i <= tail;i ++ )
59 {
60 int beg = q[i % n];
61 vst[beg] = false ;
62 for (edges * i = g[beg]; i != NULL; i = i -> next)
63 {
64 int tmp = i -> v, val = i -> val;
65 if (dist[tmp] > dist[beg] + val)
66 {
67 dist[tmp] = dist[beg] + val;
68 if ( ! vst[tmp])
69 {
70 vst[tmp] = true ;
71 cnt[tmp] ++ ;
72 tail ++ ;
73 q[tail % n] = tmp;
74 if (cnt[tmp] > n)
75 {
76 puts( " -1 " );
77 return ;
78 }
79 }
80 }
81 }
82 }
83 for ( int i = 1 ;i < n - 1 ;i ++ )
84 printf( " %d " , dist[i] - dist[i - 1 ]);
85 puts( "" );
86 }
87
88 int main()
89 {
90 int n ,a0, b0, l0, a1, b1, l1;
91 while (scanf( " %d %d %d %d %d %d %d " , & n, & a0, & b0, & l0, & a1, & b1, & l1) == 7 )
92 {
93 initialize();
94 for ( int i = 1 ;i + l0 - 1 <= n;i ++ )
95 {
96 addedge(i - 1 , i + l0 - 1 , l0 - a0);
97 addedge(i + l0 - 1 , i - 1 , b0 - l0);
98 }
99 for ( int i = 1 ;i + l1 - 1 <= n;i ++ )
100 {
101 addedge(i - 1 , i + l1 - 1 , b1);
102 addedge(i + l1 - 1 , i - 1 , - a1);
103 }
104 for ( int i = 1 ;i <= n;i ++ )
105 {
106 addedge(i - 1 , i, 1 );
107 addedge(i, i - 1 , 0 );
108 }
109 for ( int i = 0 ;i <= n;i ++ )
110 {
111 addedge(n + 1 , i, 0 );
112 }
113 SPFA(n + 2 );
114 }
115 return 0 ;
116 }
得出的结论,SPFA的效率比bellman-ford要高很多,没有负环的时候SPFA效率远远要好。
注意人工定点的原因是要把图联通起来,所以设立的。
如果不设立人工定点,只要把所有的点先都扔到队列里就可以了
然后memset(dist, 0, sizeof(dist));再SPFA就可以求解差分约束了。
其他的内容以后再总结。
今天由于一个Bellman-ford 边忘清空了,耽误了一下午的时间。太水了.
先在NOI的网站上看是单case的,到spoj是多case的结果忘清空边了……我怒!!!!
附着题Bellman-Ford的代码,越想越生气,这一天就过去了,浪费了呀
1 /*
2 * =====================================================================================
3 *
4 * Filename: Bellman_ford.cpp
5 *
6 * Description: system of difference constraints
7 *
8 * Version: 1.0
9 * Created: 2011年03月01日 14时14分24秒
10 * Revision: none
11 * Compiler: gcc
12 *
13 * Author: ronaflx
14 * Company: hit-acm-group
15 *
16 * =====================================================================================
17 */
18 #include < iostream >
19 #include < cstring >
20 #include < cstdio >
21 #include < vector >
22 using namespace std;
23 const int SIZE = 10110 ;
24 const int INF = 100000000 ;
25 vector < pair < pair < int , int > , int > > edge;
26 int n, a0, a1, b0, b1, l0, l1;
27 int d[SIZE];
28
29 void Bellman_ford( int n, int p)
30 {
31 fill(d,d + n, INF);
32 d[n - 1 ] = 0 ;
33 for ( int i = 1 ;i < n;i ++ )
34 {
35 bool unfind = true ;
36 for (vector < pair < pair < int , int > , int > > ::iterator i = edge.begin(); i != edge.end(); i ++ )
37 {
38 int v = i -> first.first, u = i -> first.second, val = i -> second;
39 if (d[u] > d[v] + val)
40 {
41 unfind = false ;
42 d[u] = d[v] + val;
43 }
44 }
45 if (unfind)
46 break ;
47 }
48 for (vector < pair < pair < int , int > , int > > ::iterator i = edge.begin(); i != edge.end(); i ++ )
49 {
50 int v = i -> first.first, u = i -> first.second, val = i -> second;
51 if (d[u] > d[v] + val)
52 {
53 puts( " -1 " );
54 return ;
55 }
56 }
57 for ( int i = 1 ;i <= p;i ++ )
58 printf( " %d " , d[i] - d[i - 1 ]);
59 puts( "" );
60 }
61 int main()
62 {
63 while (scanf( " %d %d %d %d %d %d %d " , & n, & a0, & b0, & l0, & a1, & b1, & l1) == 7 )
64 {
65 edge.clear();
66 for ( int i = 1 ;i + l0 - 1 <= n;i ++ )
67 {
68 edge.push_back(make_pair(make_pair(i - 1 , i + l0 - 1 ), l0 - a0));
69 edge.push_back(make_pair(make_pair(i + l0 - 1 , i - 1 ), b0 - l0));
70 }
71 for ( int i = 1 ;i + l1 - 1 <= n;i ++ )
72 {
73 edge.push_back(make_pair(make_pair(i - 1 , i + l1 - 1 ), b1));
74 edge.push_back(make_pair(make_pair(i + l1 - 1 , i - 1 ), - a1));
75 }
76 for ( int i = 1 ;i <= n;i ++ )
77 {
78 edge.push_back(make_pair(make_pair(i - 1 , i), 1 ));
79 edge.push_back(make_pair(make_pair(i, i - 1 ), 0 ));
80 }
81 for ( int i = 0 ;i <= n;i ++ )
82 edge.push_back(make_pair(make_pair(n + 1 , i), 0 ));
83 Bellman_ford(n + 2 , n);
84 }
85 return 0 ;
86 }