POJ 3259 Wormholes 【Floyd判斷負環】

POJ 3259 Wormholes 【Floyd判斷負環】

題目大意:
FJ 有 N 塊田野【編號 1…n】田野間有 M 條路【雙向】
同時有 W 個蟲洞,通過這個蟲洞到達另一個田野,可以回到一段時間以前【單向】
問:FJ 是否能在田地中遇到以前的自己

具體思路:
雙向路爲正權,單向路爲負權,判斷圖中是否存在負環,存在則可以遇到以前的自己,至於爲什麼上一篇博客有解釋
可用spfa求解,但是spfa是針對單源點的,此題沒有指定源點,因此無法ac
至於那些默認1號田野爲出發點的能ac可能是因爲題目給的測試數據是連通圖
因此本題更適合用floyd判斷負權(下方我也貼出spfa以1號爲出發點的代碼)
初始化到自身的時間爲0到其它田野的時間爲無窮,若存在負環,最終到自身的時間會被松馳爲負值,(可以遇到以前的自己)

具體代碼:

//floyd
#include<iostream>
#include<cstdio>
#include<stdlib.h>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 505;
const int INF = 1e9;
int maps[N][N];
int F, n, m, w;

void init()
{
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (i == j) maps[i][j] = 0;	//初始化到自身的時間爲0
			else maps[i][j] = INF;	//到其它田野的時間爲無窮大
}
bool floyd()
{

	for(int k=1;k<=n;k++)
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
				if (maps[i][j] > maps[i][k] + maps[k][j])
					maps[i][j] = maps[i][k] + maps[k][j];
			if (maps[i][i] < 0)return true;
		}
	return false;
}

int main()
{
	cin >> F;
	while (F--)
	{
		cin >> n >> m >> w;
		init();
		for (int i = 1; i <= m + w; i++)
		{
			int x, y, t;
			cin >> x >> y >> t;
			if (i <= m )
			{
				if(t < maps[x][y])//考慮重邊
					maps[x][y] = maps[y][x] = t;
			}
			else maps[x][y] = -t;	//蟲洞是單向的,其實我絕對這裏也應該考慮重邊,但是沒有也能ac
		}
		if (floyd())printf("YES\n");
		else printf("NO\n");
	}

	return 0;
}

順便貼出spfa的做法(1號爲出發點)

//spfa
#include<iostream>
#include<cstdio>
#include<stdlib.h>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 505;
const int INF = 1e9;
struct Node {
	int x, y, t;	//x->y這條路/蟲洞耗時t
	Node(int x, int y, int t) { this->x = x, this->y = y, this->t = t; }
};
vector<Node> maps[N];
int visit[N];	//記錄是否在隊列中
int index[N];	//記錄入隊次數
int d[N];		//d[i]表示穿梭到田野i的時間
int F, n, m, w;
int flag = 0;

void spfa()
{
	for (int i = 1; i <= n; i++)
		visit[i] = 0, index[i] = 0, d[i] = INF;
	visit[1] = 1;
	index[1] = 1;
	d[1] = 0;
	queue<int> q;
	q.push(1);
	while (q.size())
	{
		int t = q.front();
		q.pop();
		visit[t] = 0;
		for (vector<Node>::iterator it = maps[t].begin(); it != maps[t].end(); it++)
		{
			if (d[it->y] > d[t] + it->t) {
				d[it->y] = d[t] + it->t;
				if (!visit[it->y]) {
					visit[it->y] = 1;
					q.push(it->y);
					index[it->y]++;
					if (index[it->y] > n) {
						flag = 1;
						return;
					}
				}
			}

		}
	}
}

int main()
{
	//freopen("C:\\Users\\Tsai\\Desktop\\in.txt", "r", stdin);
	cin >> F;
	while (F--)
	{
		cin >> n >> m >> w;
		for (int i = 1; i <= m + w; i++)
		{
			int x, y, t;
			cin >> x >> y >> t;
			if (i <= m) {
				maps[x].push_back(Node(x, y, t));	//路是雙向的
				maps[y].push_back(Node(y, x, t));
			}
			else maps[x].push_back(Node(x, y, -t));	//蟲洞是單向的
		}
		spfa();
		if (flag)printf("YES\n");
		else printf("NO\n");
		for (int i = 1; i <= n; i++)
			maps[i].clear();
		flag = 0;
	}

	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章