#106-[差分约束]关系运算图

版权声明:反正也没有人会转,下一个 https://blog.csdn.net/drtlstf/article/details/82811685

Description

给出一有向图,图中每条边都被标上了关系运算符‘<’,‘>’,‘=’。现在要给图中每个顶点标上一个大于等于0,小于等于k的某个整数使所有边上的符号得到满足。若存在这样的k,则求最小的k,若任何k都无法满足则输出NO。

 

例如下表中最小的k为2。

 

结点1>结点2

结点2>结点3

结点2>结点4

结点3=结点4

 

如果存在这样的k,输出最小的k值;否则输出‘NO’。

Input

共二行,第一行有二个空格隔开的整数n和m。n表示G的结点个数,m表示G的边数,其中1<=n<=1000, 0<=m<=10000。全部结点用1到n标出,图中任何二点之间最多只有一条边,且不存在自环。

第二行共有3m个用空格隔开的整数,第3i-2和第3i-1(1<=i<=m)个数表示第i条边的顶点。第3i个数表示第i条边上的符号,其值用集合{-1,0,1}中的数表示:-1表示‘<’, 0 表示‘=’, 1表示‘>’。

Output

仅一行,如无解则输出‘NO’;否则输出最小的k的值。

Sample Input

4 4
1 2 -1 2 3 0 2 4 -1 3 4 -1

Sample Output

2

差分约束比较模板的一道题,求最小值用SPFA最长路.

#include <iostream>
#include <cstring>
#include <queue>

#define SIZE 1010
#define INF 1e+09

using namespace std;

struct edge // 定义一条边的结构体.
{
	int to, dis;
};

vector<edge> graph[SIZE];
queue<int> q;
int dis[SIZE], count[SIZE], n;
bool inqueue[SIZE];

void spfa(void) // SPFA最长路
{
	int u, v, w, i, res = 0;
	
	for (i = 1; i <= n + 1; ++i)
	{
		dis[i] = -INF;
	}
	q.push(0);
	inqueue[0] = true;
	++count[0];
	while (!q.empty())
	{
		u = q.front();
		q.pop();
		inqueue[u] = false;
		for (i = 0; i < graph[u].size(); ++i)
		{
			v = graph[u][i].to;
			w = graph[u][i].dis;
			if (dis[v] < dis[u] + w) // 这里条件换一下就可以了
			{
				dis[v] = dis[u] + w;
				if (!inqueue[v])
				{
					if (++count[v] >= n) // 存在正环
					{
						printf("NO");
						return;
					}
					q.push(v);
					inqueue[v] = true;
				}
			}
		}
	}
	
	printf("%d", dis[n+1]);
	
	return;
}

int main(int argc, char** argv)
{
	int m, u, v, w, i;
	
	scanf("%d%d", &n, &m);
	while (m--)
	{
		scanf("%d%d%d", &u, &v, &w);
		switch (w) // 建图!
		{
			case -1:
				graph[u].push_back({v, 1});
				break;
			case 0:
				graph[u].push_back({v, 0});
				graph[v].push_back({u, 0});
				break;
			case 1:
				graph[v].push_back({u, 1});
				break;
		}
	}
	
	for (i = 1; i <= n; ++i)
	{
		graph[0].push_back({i, 0});
		graph[i].push_back({n + 1, 0});
	}
	spfa();
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/drtlstf/article/details/82811685