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

题意很明确了

采用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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值