1. 程式人生 > >POJ3259 農場與蟲洞 圖論(Bellman-Ford求負環)

POJ3259 農場與蟲洞 圖論(Bellman-Ford求負環)

嗯圖論的第二道題,剛剛有一點點入門的感覺www。

於是就把心得體會寫下來啦。

題目概述:

主人公農夫有幾片農場,然後農場裡有各個農田(這個模型化為圖的端點),然後各個農田之間有路徑(這個模型化為圖的邊),然後有的邊是正常的無向邊,以及有的邊是有項的蟲洞。開始的時候時間為0,通過一條正常邊會加時間,通過蟲洞減去時間。

輸入N(1-500),M(1-2500),W(1-100),然後輸出能否通過一條路徑回到過去,也就是模型中的負權環。

演算法思想:

求負權顯然的Bellman-Ford,可是還是太慢了要400多MS,不知道先進的方法是怎麼樣的。果然要看下SPFA麼。。

大概跟標準模版無差,值得一提的是,這種演算法求負權環有兩種方式,第一種是求完最短路徑然後繼續檢查更新,第二種是直接看更新能不能進行到第n-1次,兩種程式碼我都實現了一遍,速度也並沒有太大的差異。就列在下面了。

程式碼部分:

程式碼1:

#include <iostream>
using namespace std;
int N;int n,m,w;
int MAX = 21474836;

struct edge{
	int from,to,cost;
};

int d[555];bool flag;
edge e[5600];

void init() {
	flag = false;
	cin >> n >> m >> w;
	for (int i=0;i<n;i++){
		d[i] = MAX;
	}
	d[0] = 0;
	for (int i=0;i<2*m;i+=2){
		int a,b,c;
		cin >> a >> b >> c;
		e[i].from = a;
		e[i].to = b;
		e[i].cost = c;
		e[i+1].from = b;
		e[i+1].to = a;
		e[i+1].cost = c;
	}
	for (int i=2*m;i<2*m+w;i++){
		int a,b,c;
		cin >> a >> b >> c;
		e[i].from = a;
		e[i].to = b;
		e[i].cost = c*(-1);
	}
}

bool b_f() {
	for (int i=0;i<n-1;i++){
		for (int j=0;j<2*m+w;j++){
			if (d[e[j].from] != MAX && d[e[j].to] > d[e[j].from]+e[j].cost) {
				d[e[j].to] = d[e[j].from]+e[j].cost;
			}
		}
	}

	for (int j=0;j<2*m+w;j++){
		if (d[e[j].to] > d[e[j].from]+e[j].cost) {
			return true;
		}
	}
	return false;

}


int main() {
	cin >> N;
	for (int k=0; k<N; ++k){
		init();
		if (b_f()) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	return 0;
}

程式碼2:
#include <iostream>
#include <string.h>
using namespace std;
int N;int n,m,w;

struct edge{
	int from,to,cost;
};

int d[555];
edge e[5600];

void init() {
	cin >> n >> m >> w;
	memset(d,0,sizeof(d));
	for (int i=0;i<m*2;i+=2){
		int a,b,c;
		cin >> a >> b >> c;
		e[i].from = a;
		e[i].to = b;
		e[i].cost = c;
		e[i+1].from = b;
		e[i+1].to = a;
		e[i+1].cost = c;
	}
	for (int i=2*m;i<2*m+w;i++){
		int a,b,c;
		cin >> a >> b >> c;
		e[i].from = a;
		e[i].to = b;
		e[i].cost = c*(-1);
	}
}

bool b_f() {
	for (int i=0;i<n;i++){
		for (int j=0;j<2*m+w;j++){
			if (d[e[j].to] > d[e[j].from]+e[j].cost) {
				d[e[j].to] = d[e[j].from]+e[j].cost;
				if (i == n-1) return true;
			}
		}
	}
	return false;
}


int main() {
	cin >> N;
	for (int k=0; k<N; ++k){
		init();
		if (b_f()) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	return 0;
}