差分约束-Spfa 配题 (POJ 1201)

对于上述的不等式问题,将X看成dis,将下标看成点,那么dis[v] \leq dis[u] + w这就是一个典型的最短路问题。

建图:

  • X_{a} - X_{b} \leq c,建一条从b指向a的边,最后求最短路
  • X_{a}-X_{b}\geq c,建一条从b指向a的边,最后求最长路
  • X_{a}-X_{b}=c,将其转化为\left\{\begin{matrix} X_{a}-X_{b}\leq c\\ X_{a}-X_{b}\geq c \end{matrix}\right.,然后统一到最长路或者最短路格式即可

对于差分约束系统存在两种结果:

  • 无解,最短(长)路无解
  • 无穷多解,随便给出一个最短(长)路解,即可

配题:POJ 1201

题意:给n个区间,然后每个区间必须包含c个整数。

问:满足这n个条件的前提下,最少需要选择多少个点?

思想:差分约束系统主要的问题是寻找函数X,然后根据函数X的下标建图即可:

  • \left\{\begin{matrix} X[b]-X[a-1]\geq c\\ 0\leq X[i]-X[I-1]\leq 1 \end{matrix}\right.
  • 将第二式子拆分即可,这是对一组区间的不等式集合,然后对所有区间做同样的事情,建图。

NOTE:scanf,函数内开数组容易RE

#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
const int max_n = 50010;
const int INF = 0x7fffffff;
int n;
struct NODE
{
	int v;
	int w;
};
vector<NODE>graph[max_n];
int dis[max_n];
int vis[max_n];
int spfa(const int source, const int sink)
{
	queue<int>q;	
	while (!q.empty()) q.pop();
	memset(vis, false, sizeof(vis));
	for (int i = 0; i < max_n; i++)
	{
		dis[i] = -INF;
	}
	
	dis[source] = 0;
	vis[source] = true;
	q.push(source);
	
	while (!q.empty())
	{
		int cur_node = q.front();
		q.pop();
		vis[cur_node] = false;
		for (int i = 0; i < graph[cur_node].size(); i++)
		{
			int next_node = graph[cur_node][i].v;
			int w = graph[cur_node][i].w;
			if (dis[next_node] < dis[cur_node] + w)
			{
				dis[next_node] = dis[cur_node] + w;
				if (vis[next_node] == false)
				{
					vis[next_node] = true;
					q.push(next_node);
				}
			}
		}
	}
	return dis[sink];
}

int main()
{
	while (cin>> n)
	{
		int min_num = INF, max_num = -1;
		for (int i = 0; i < max_n; i++)
		{
			graph[i].clear();	
		}
		for (int i = 1; i <= n; i++)
		{
			NODE node;
			int a, b, c;
			// cin>> a>> b>> c;
			scanf("%d %d %d", &a, &b, &c);
			node.v = b;
			node.w = c;
			graph[a - 1].push_back(node);
			if (a-1 < min_num)
			{
				min_num = a-1;
			}
			if (a-1 > max_num)
			{
				max_num = a-1;
			} 
			if (b < min_num)
			{
				min_num = b;
			}
			if (b > max_num)
			{
				max_num = b;
			}
		}
		for (int i = min_num; i <= max_num; i++)
		{
			NODE node;
			node.v = i;
			node.w = 0;
			graph[i - 1].push_back(node);
			node.v = i - 1;
			node.w = -1;
			graph[i].push_back(node);
		}
		cout<< spfa(min_num, max_num)<< endl;
	}
	return 0;
}
发布了331 篇原创文章 · 获赞 135 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/Triple_WDF/article/details/102293947