对于上述的不等式问题,将X看成dis,将下标看成点,那么这就是一个典型的最短路问题。
建图:
- ,建一条从b指向a的边,最后求最短路
- ,建一条从b指向a的边,最后求最长路
- ,将其转化为,然后统一到最长路或者最短路格式即可
对于差分约束系统存在两种结果:
- 无解,最短(长)路无解
- 无穷多解,随便给出一个最短(长)路解,即可
配题:POJ 1201
题意:给n个区间,然后每个区间必须包含c个整数。
问:满足这n个条件的前提下,最少需要选择多少个点?
思想:差分约束系统主要的问题是寻找函数,然后根据函数的下标建图即可:
- 将第二式子拆分即可,这是对一组区间的不等式集合,然后对所有区间做同样的事情,建图。
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;
}