LightOJ-1074 Extended Traffic (最短路-Bellman_Ford存在负环)

题目链接

题意:给出t组样例,每组给出一个n,表示n个点,给出n-1组数据a[]表示每2~n地点上的人流量,下面给出m条路,路的权值为人流公式(a[i]-a[j])^3,故存在负环的情况,题目再给出一个q表示q次询问,询问起点1到x点的最短距离.

题解:不能用Dijsktra,只能用Bellman_Ford解决带负权问题,且它们之间若存在负环或者dis[x]<3 输出?其余输出dis[a].

代码如下:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn = 500;
struct edge
{
	int u, v, w;
	edge() {}
	edge(int uu, int vv, int ww) :u(uu), v(vv), w(ww) {}
};
vector<edge> e;
int dis[maxn], n;
bool vis[maxn], flag[maxn];
int a[maxn];
void Bellman_Ford()
{
	vis[1] = true;
	for (int k = 1; k<n; k++) //n-1次松弛
		for (int i = 0; i<e.size(); i++)
		{
			edge &p = e[i];
			if (vis[p.u] && ((!vis[p.v]) || (dis[p.u] + p.w<dis[p.v])))
			{
				vis[p.v] = true;
				dis[p.v] = dis[p.u] + p.w;
			}
		}
	for (int i = 0; i<e.size(); i++)
	{
		edge &p = e[i];
		if (vis[p.u] && ((!vis[p.v]) || (dis[p.u] + p.w<dis[p.v])))  //判断该点是否还能进行松弛,能-》存在负环
			flag[p.v] = true;
	}
}
void init()
{
	e.clear();
	memset(vis, 0, sizeof(vis));
	memset(flag, 0, sizeof(flag));
	memset(dis, 0, sizeof(dis));
}
int main()
{
	int t, m, cas = 1;
	scanf("%d", &t);
	while (t--)
	{
		init();
		printf("Case %d:\n", cas++);
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i]);
		scanf("%d", &m);
		while (m--) //m条有向边
		{
			int u, v;
			scanf("%d%d", &u, &v);
			e.push_back(edge(u, v, (a[v] - a[u])*(a[v] - a[u])*(a[v] - a[u]))); //题目公式
		}
		Bellman_Ford();
		scanf("%d", &m);
		while (m--)
		{
			int p;
			scanf("%d", &p);
			if (flag[p] || dis[p]<3)printf("?\n");
			else printf("%d\n", dis[p]);
		}
	}
}




 

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/weixin_41156591/article/details/81871624
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞