POJ——3259 chong 虫洞

 
 

利用虫洞的时光旅行,很有趣的一道题。涉及到图论的知识,关键是构造图,用Bellman-Ford算法找出负权环

Bellman-Ford算法核心在于松弛,具体可以百度,这里就不重复前人的智慧了O(∩_∩)O哈哈~

需要注意的就是输入说明Input这部分,很多人读不懂这段题意:

正权(双向)边部分: Line 1 of each farm: Three space-separated integers respectively: NM, and W

Lines 2~M+1 of each farm: Three space-separated numbers (SET) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse.

Two fields might be connected by more than one path.

 

负权(单向)边部分: Lines M+2~M+W+1 of each farm: Three space-separated numbers (SET) that describe, respectively: A one way path from S to E that also moves the traveler back T seconds.

#include<iostream>  
using namespace std;

int dis[1001];      //源点到各点权值  
const int max_w = 10001;      //无穷远  

class weight
{
public:
	int s;
	int e;
	int t;
}edge[5200];

int N, M, W_h; //N (1≤N≤500)fields 顶点数  
			   //M (1≤M≤2500)paths 正权双向边  
			   //W_h (1≤W≤200) wormholes 虫洞(回溯),负权单向边  
int all_e;   //边集(边总数)  

bool bellman(void)
{
	bool flag;
	for (int i = 1; i <= N; i++)
		cout << dis[i] << endl;
	/*relax*/
	for (int i = 0; i<N - 1; i++)
	{
		flag = false;
		for (int j = 0; j<all_e; j++)
			if (dis[edge[j].e] > dis[edge[j].s] + edge[j].t)
			{
				cout << dis[edge[j].s] << endl;
				cout << dis[edge[j].e] << endl;
				cout << edge[j].t << endl;
				cout << edge[j].e << endl;
				dis[edge[j].e] = dis[edge[j].s] + edge[j].t;
				flag = true;         //relax对路径有更新  
			}
		if (!flag)
			break;  //只要某一次relax没有更新,说明最短路径已经查找完毕,或者部分点不可达,可以跳出relax  
	}


	/*Search Negative Circle*/

	for (int k = 0; k<all_e; k++)
		if (dis[edge[k].e] > dis[edge[k].s] + edge[k].t)
			return true;

	return false;
}
int main(void)
{
	int u, v, w;
	int F;
	cin >> F;
	while (F--)
	{
		memset(dis, max_w, sizeof(dis));    //源点到各点的初始值为无穷,即默认不连通  

		cin >> N >> M >> W_h;

		all_e = 0;      //初始化指针  

						/*read in Positive Paths*/

		for (int i = 1; i <= M; i++)
		{
			cin >> u >> v >> w;
			edge[all_e].s = edge[all_e + 1].e = u;
			edge[all_e].e = edge[all_e + 1].s = v;
			edge[all_e++].t = w;
			edge[all_e++].t = w;               //由于paths的双向性,两个方向权值相等,注意指针的移动  
		}

		/*read in Negative Wormholds*/

		for (int j = 1; j <= W_h; j++)
		{
			cin >> u >> v >> w;
			edge[all_e].s = u;
			edge[all_e].e = v;
			edge[all_e++].t = -w;     //注意权值为负  
		}

		/*Bellman-Ford Algorithm*/

		if (bellman())
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/usernamezzz/article/details/79943757