1. Dijkstra算法
这个算法和prime求最小生成树特别像,都是找到最小边,把点加进来,然后用新加的点更新其他没有被加进来的点。
不断维护一个队列,如果队列里的点,使得其他点的最短路得到松弛,则这个点还有可能使另外的点松弛,所以如果这个点不在队列里,就把它入队。
很多时候,给定的图存在负权边,这时类似Dijkstra等 算法 便没有了用武之地,而Bellman-Ford 算法 的复杂度又过高, SPFA 算法 便派上用场了。 此算法时间复杂度为O(2*E),E为边数。
这个算法和prime求最小生成树特别像,都是找到最小边,把点加进来,然后用新加的点更新其他没有被加进来的点。
1
.
#define N 1002
2 .
#define MAX 99999
3 .
int edges[N][N],d[N],n;
4 .
5 .
void dijkstra( int v)
6 .
{
7 .
int i,j;
8 .
bool s[N] = { false };
9 .
for (i = 1 ;i <= n;i ++ )
10 .
d[i] = edges[v][i];
11 .
d[v] = 0 ;s[v] = true ;
12 .
for (i = 1 ;i < n;i ++ )
13 .
{
14 .
int temp = MAX;
15 .
int u = v;
16 .
for (j = 1 ;j <= n;j ++ )
17 .
if (( ! s[j]) && (d[j] < temp))
18 .
{
19 .
u = j;
20 .
temp = d[j];
21 .
}
22 .
s[u] = true ;
23 .
for (j = 1 ;j <= n;j ++ )
24 .
if (( ! s[j]) && (edges[u][j] < MAX) && (d[u] + edges[u][j]) < d[j])
25 .
d[j] = d[u] + edges[u][j];
26 .
}
27 .
28 .
}
2. SPFA算法 (shortest path faster algorithm)
#define N 1002
2 .
#define MAX 99999
3 .
int edges[N][N],d[N],n;
4 .
5 .
void dijkstra( int v)
6 .
{
7 .
int i,j;
8 .
bool s[N] = { false };
9 .
for (i = 1 ;i <= n;i ++ )
10 .
d[i] = edges[v][i];
11 .
d[v] = 0 ;s[v] = true ;
12 .
for (i = 1 ;i < n;i ++ )
13 .
{
14 .
int temp = MAX;
15 .
int u = v;
16 .
for (j = 1 ;j <= n;j ++ )
17 .
if (( ! s[j]) && (d[j] < temp))
18 .
{
19 .
u = j;
20 .
temp = d[j];
21 .
}
22 .
s[u] = true ;
23 .
for (j = 1 ;j <= n;j ++ )
24 .
if (( ! s[j]) && (edges[u][j] < MAX) && (d[u] + edges[u][j]) < d[j])
25 .
d[j] = d[u] + edges[u][j];
26 .
}
27 .
28 .
}
不断维护一个队列,如果队列里的点,使得其他点的最短路得到松弛,则这个点还有可能使另外的点松弛,所以如果这个点不在队列里,就把它入队。
很多时候,给定的图存在负权边,这时类似Dijkstra等 算法 便没有了用武之地,而Bellman-Ford 算法 的复杂度又过高, SPFA 算法 便派上用场了。 此算法时间复杂度为O(2*E),E为边数。
//
pku1860
#include < stdio.h >
#include < string .h >
#include < vector >
#define N 120
using namespace std;
struct Point
{
int id;
double r, c;
};
vector < Point > p[N];
int q[N],n,m,S,visit[N];
double V,dist[N];
int spfa()
{
memset(visit, 0 , sizeof (visit));
int i,j,head = 0 ,tail = 1 ,x;
for (i = 1 ; i <= n ;i ++ )
dist[i] = 0 ; // 此题是求换得的货币最多,所以初值赋0;
// 若求最短路,初值应赋为无穷大
if (V <= 0 ) return 0 ;
q[ 0 ] = S;
dist[S] = V; // S为源,若求最短路,则dist[S]=0;
visit[S] = 1 ;
while (head != tail){ // Attention!!!由于对队列长度取模了,所以head<tail不一定成立,应改为head!=tail
x = q[head];
visit[x] = 0 ;
head = (head + 1 ) % N;
for (i = 0 ; i < p[x].size(); i ++ ){
j = p[x][i].id;
if (dist[j] < (dist[x] - p[x][i].c) * p[x][i].r){
dist[j] = (dist[x] - p[x][i].c) * p[x][i].r;
if ( ! visit[j]){
q[tail] = j;
tail = (tail + 1 ) % N;
visit[j] = 1 ; // 若如果j点的最短路径估计值有所调整,
// 且j点不在当前的队列中,就将j点放入队尾
}
}
}
if (dist[S] > V) return 1 ;
}
return 0 ;
}
int main()
{
int i,j,a,b;
double rab, cab, rba, cba;
Point p1, p2;
while (scanf( " %d %d %d %lf " , & n, & m, & S, & V) != EOF){
for (i = 1 ; i <= n; i ++ )
p[i].clear();
for (i = 0 ; i < m; i ++ ){
scanf( " %d %d %lf %lf %lf %lf " , & a, & b, & rab, & cab, & rba, & cba);
p1.id = b; p1.r = rab; p1.c = cab;
p2.id = a; p2.r = rba; p2.c = cba;
p[a].push_back(p1);
p[b].push_back(p2);
}
j = spfa();
if (j)
printf( " YES\n " );
else
printf( " NO\n " );
}
return 0 ;
}
#include < stdio.h >
#include < string .h >
#include < vector >
#define N 120
using namespace std;
struct Point
{
int id;
double r, c;
};
vector < Point > p[N];
int q[N],n,m,S,visit[N];
double V,dist[N];
int spfa()
{
memset(visit, 0 , sizeof (visit));
int i,j,head = 0 ,tail = 1 ,x;
for (i = 1 ; i <= n ;i ++ )
dist[i] = 0 ; // 此题是求换得的货币最多,所以初值赋0;
// 若求最短路,初值应赋为无穷大
if (V <= 0 ) return 0 ;
q[ 0 ] = S;
dist[S] = V; // S为源,若求最短路,则dist[S]=0;
visit[S] = 1 ;
while (head != tail){ // Attention!!!由于对队列长度取模了,所以head<tail不一定成立,应改为head!=tail
x = q[head];
visit[x] = 0 ;
head = (head + 1 ) % N;
for (i = 0 ; i < p[x].size(); i ++ ){
j = p[x][i].id;
if (dist[j] < (dist[x] - p[x][i].c) * p[x][i].r){
dist[j] = (dist[x] - p[x][i].c) * p[x][i].r;
if ( ! visit[j]){
q[tail] = j;
tail = (tail + 1 ) % N;
visit[j] = 1 ; // 若如果j点的最短路径估计值有所调整,
// 且j点不在当前的队列中,就将j点放入队尾
}
}
}
if (dist[S] > V) return 1 ;
}
return 0 ;
}
int main()
{
int i,j,a,b;
double rab, cab, rba, cba;
Point p1, p2;
while (scanf( " %d %d %d %lf " , & n, & m, & S, & V) != EOF){
for (i = 1 ; i <= n; i ++ )
p[i].clear();
for (i = 0 ; i < m; i ++ ){
scanf( " %d %d %lf %lf %lf %lf " , & a, & b, & rab, & cab, & rba, & cba);
p1.id = b; p1.r = rab; p1.c = cab;
p2.id = a; p2.r = rba; p2.c = cba;
p[a].push_back(p1);
p[b].push_back(p2);
}
j = spfa();
if (j)
printf( " YES\n " );
else
printf( " NO\n " );
}
return 0 ;
}