您的位置:首页 > 其它

poj 1860 2378 3259带负边最短路 ** bellman ford 模板

2013-03-26 16:49 477 查看
题意很明确了

采用FIFO的基本队列进行bellman ford计算

#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
using namespace std;

///宏定义
const int  INF = 10000000;
const int MAXN = 1257;
const int maxn = MAXN;
///全局变量 和 函数
///
struct Edge
{
int from, to;
double R, C;
};
vector<Edge> edges;   //边列表
vector<int> G[maxn];  //每个结点出发的边编号
//bool done[maxn];      //是否已永久编号
double d[maxn];          //s到各个点的距离
int N, M, S;
double V;
bool bellman_ford()
{
queue<int> q;
bool inq[maxn];
int cnt[maxn];
memset(cnt, 0, sizeof(cnt));
memset(inq, false, sizeof(inq));
memset(d, 0, sizeof(d));
d[S] = V;
q.push(S);
while(!q.empty())
{
int cur = q.front();
q.pop();
inq[cur] = false;
bool flag = false;
for(int i = 0; i < G[cur].size(); i++)
{
Edge &e = edges[ G[cur][i] ];
if (d[e.to] < (d[cur] - e.C) * e.R)
{
flag = true;
d[e.to] = (d[cur] - e.C) * e.R;
if(!inq[e.to])
{
inq[e.to] = true;
q.push(e.to);
if(++cnt[e.to] > N)
return true;
}
}
}

}
return false;
}
int main()
{

///变量定义
int i, j;
while(cin >> N >> M >> S >> V)
{
for(i = 0; i <= N; i++)
{
G[i].clear();
}
edges.clear();
for(i = 0; i < M; i++)
{
int from, to;
double R, C, R1, C1;
cin >> from >> to >> R >> C >> R1 >> C1;

Edge tmp;
tmp.from = from;
tmp.to = to;
tmp.R = R;
tmp.C = C;
edges.push_back(tmp);
int m = edges.size();
G[from].push_back(m - 1);

tmp.from = to;
tmp.to = from;
tmp.R = R1;
tmp.C = C1;
edges.push_back(tmp);
m = edges.size();
G[to].push_back(m - 1);
}
if(bellman_ford())
cout << "YES" << endl;
else
cout << "NO" << endl;
}

///结束
return 0;
}


整理一下 bellman ford 模板如下 针对 poj 2387使用

#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
using namespace std;

///宏定义
const int  INF = 10000000;
const int MAXN = 1257;
const int maxn = MAXN;
///全局变量 和 函数
///
struct Edge
{
int from, to, dist;
};

struct BellmanFord
{
int n, m;
vector<Edge> edges;    //边的存储
vector<int> G[maxn];   //点的邻接表
bool inq[maxn];        //是否在队列中
int d[maxn];           //源点到各点的距离
int p[maxn];           //最短路中的上一条弧,打印用
int cnt[maxn];         //进队次数

void init(int n)
{
this->n = n;
for(int i = 0; i <= n; i++)
G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, int dist)
{
Edge edge;
edge.from = from;
edge.to = to;
edge.dist = dist;
edges.push_back(edge);
m = edges.size();
G[from].push_back(m - 1);
}
bool negativeCycle(int s)
{
queue<int> Q;
memset(inq, 0, sizeof(inq));
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i <= n; i++)
{
d[i] = INF;
}
d[s] = 0;
inq[s] = true;
Q.push(s);
while(!Q.empty())
{
int u = Q.front();
Q.pop();
inq[u] = false;
for(int i = 0; i <G[u].size(); i++)
{
Edge& e = edges[ G[u][i] ];
if(d[e.to] > d[u] + e.dist)
{
d[e.to] = d[u] + e.dist;
p[e.to] = G[u][i];
if(!inq[e.to])
{
Q.push(e.to);
inq[e.to] = true;
if(++cnt[e.to] > n)
return true;
}
}
}
}
return false;
}
};
int t, n;
//int N, M, S, V;
int main()
{
///变量定义
int i, j;
while(scanf("%d %d", &t, &n) != EOF)
{

BellmanFord bellman_ford;
bellman_ford.init(n);
for(i = 0; i < t; i++)
{
int from, to, weight;
scanf("%d %d %d", &from, &to, &weight);
bellman_ford.AddEdge(from, to, weight);
bellman_ford.AddEdge(to, from, weight);
}
bellman_ford.negativeCycle(n);

int ans = bellman_ford.d[1];
printf("%d\n", ans);

}

///结束
return 0;
}


同样的方式,针对poj 1860 货币交换 进行应用

注意到 修改的地方是

Edge的定义 以及松弛的规则(因为现在是判断正环的存在性)

#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
using namespace std;

///宏定义
const int  INF = 10000000;
const int MAXN = 1257;
const int maxn = MAXN;
///全局变量 和 函数
///
int N, M, S;
double V;

struct Edge
{
//	int from, to, dist;
//根据题意修改结构体,上面的是原来的定义
int from, to;
double R, C;
};

struct BellmanFord
{
int n, m;
vector<Edge> edges;    //边的存储
vector<int> G[maxn];   //点的邻接表
bool inq[maxn];        //是否在队列中
//	int d[maxn];           //源点到各点的距离
double d[maxn];        //根据题意采用double类型
int p[maxn];           //最短路中的上一条弧,打印用
int cnt[maxn];         //进队次数

void init(int n)
{
this->n = n;
for(int i = 0; i <= n; i++)
G[i].clear();
edges.clear();
}
/*
void AddEdge(int from, int to, int dist)
{
Edge edge;
edge.from = from;
edge.to = to;
edge.dist = dist;
edges.push_back(edge);
m = edges.size();
G[from].push_back(m - 1);
}*/
//可对比原始的定义
void AddEdge(int from, int to, double R, double C)
{
Edge edge;
edge.from = from;
edge.to = to;
edge.R = R;
edge.C = C;
edges.push_back(edge);
m = edges.size();
G[from].push_back(m - 1);
}
bool negativeCycle(int s)
{
queue<int> Q;
memset(inq, 0, sizeof(inq));
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i <= n; i++)
{
//			d[i] = INF;
//根据题意修改为0
d[i] = 0;
}
d[s] = V; //根据题意为初始钱数
inq[s] = true;
Q.push(s);
while(!Q.empty())
{
int u = Q.front();
Q.pop();
inq[u] = false;
for(int i = 0; i <G[u].size(); i++)
{
Edge& e = edges[ G[u][i] ];
//根据题意修改松弛方法
/*
if(d[e.to] > d[u] + e.dist)
{
d[e.to] = d[u] + e.dist;
p[e.to] = G[u][i];
if(!inq[e.to])
{
Q.push(e.to);
inq[e.to] = true;
if(++cnt[e.to] > n)
return true;
}
}*/
if(d[e.to] < (d[u] - e.C) * e.R )
{
d[e.to] = (d[u] - e.C) * e.R;
//				p[e.to] = G[u][i];
if(!inq[e.to])
{
Q.push(e.to);
inq[e.to] = true;
if(++cnt[e.to] > n)
return true; //存在正环
}
}
}
}
return false;
}
};

int main()
{

///变量定义
int i, j;
while(cin >> N >> M >> S >> V)
{
BellmanFord bellman_ford;
bellman_ford.init(N);
for(i = 0; i < M; i++)
{
int from, to;
double R, C, R1, C1;
cin >> from >> to >> R >> C >> R1 >> C1;
bellman_ford.AddEdge(from, to, R, C);
bellman_ford.AddEdge(to, from, R1, C1);
}
if (bellman_ford.negativeCycle(S))
cout << "YES" << endl;
else
cout << "NO" << endl;
}

///结束
return 0;
}


用同样的方法解poj 3259 时光穿梭

#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
using namespace std;

///宏定义
const int  INF = 10000000;
const int MAXN = 1257;
const int maxn = MAXN;
///全局变量 和 函数
///

struct Edge
{
int from, to, dist;
};

struct BellmanFord
{
int n, m;
vector<Edge> edges;    //边的存储
vector<int> G[maxn];   //点的邻接表
bool inq[maxn];        //是否在队列中
int d[maxn];           //源点到各点的距离
int p[maxn];           //最短路中的上一条弧,打印用
int cnt[maxn];         //进队次数

void init(int n)
{
this->n = n;
for(int i = 0; i <= n; i++)
G[i].clear();
edges.clear();
}

void AddEdge(int from, int to, int dist)
{
Edge edge;
edge.from = from;
edge.to = to;
edge.dist = dist;
edges.push_back(edge);
m = edges.size();
G[from].push_back(m - 1);
}

bool negativeCycle(int s)
{
queue<int> Q;
memset(inq, 0, sizeof(inq));
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i <= n; i++)
{
d[i] = INF;
//根据题意修改为0
}
d[s] = 0; //根据题意为初始钱数
inq[s] = true;
Q.push(s);
while(!Q.empty())
{
int u = Q.front();
Q.pop();
inq[u] = false;
for(int i = 0; i <G[u].size(); i++)
{
Edge& e = edges[ G[u][i] ];
//根据题意修改松弛方法

if(d[e.to] > d[u] + e.dist)
{
d[e.to] = d[u] + e.dist;
//					p[e.to] = G[u][i];
if(!inq[e.to])
{
Q.push(e.to);
inq[e.to] = true;
if(++cnt[e.to] > n)
return true;
}
}

}
}
return false;
}
};
int T;
int N, M, W;
int main()
{
///变量定义
int i, j;
cin >> T;
while (T--)
{
cin >> N >> M >> W;
BellmanFord bellman_ford;
bellman_ford.init(N);
for (i = 0; i < M; i++)
{
int S, E, T;
cin >> S >> E >> T;
bellman_ford.AddEdge(S, E, T);
bellman_ford.AddEdge(E, S, T);
}
for (i = 0; i < W; i++)
{
int S, E, T;
cin >> S >> E >> T;
bellman_ford.AddEdge(S, E, -T);
}
if (bellman_ford.negativeCycle(1))
{
cout << "YES" << endl;
}
else
cout << "NO" << endl;

}

///结束
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: