题意:给定一些区间和每个区间内的元素数量(选一些互不相同的整数作为区间内的元素,每个整数只至多选1次),问最少有多少个元素(所有元素不能重复)。
分析:这题是用spfa做差分约束。不能向bellman一样。还是把差分约束理解为求最长路比较直观。
对于dist[a]-dist[b]>=c,我们可以看作dist[a]>=dist[b]+c,所以我们如果初始化为负无穷,起点初始化为0,并让所有的不等式都满足,那么就是在求一个最长路。
首先用数组sum[i]表示小于等于i的元素有多少个。这样区间[a+1,b]的元素个数要求c,可以表示为sum[b]-sum[a]>=c。还要注意每个元素要么选要么不选,其数量只能是0或1。因此,0<=sum[i]-sum[i-1]<=1
View Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
usingnamespace std;
#define maxn 50005
#define INF 0x3f3f3f3f
int pnt[maxn *3], cost[maxn *3], nxt[maxn *3];
int e, head[maxn];
int dist[maxn];
bool vis[maxn];
int n, mmin, mmax;
int relax(int u, int v, int c)
{
if (dist[v] < dist[u] + c)
{
dist[v] = dist[u] + c;
return1;
}
return0;
}
inline void addedge(int u, int v, int c)
{
pnt[e] = v;
cost[e] = c;
nxt[e] = head[u];
head[u] = e++;
}
int SPFA(int src, int n)
{
int i;
for (i = src; i <= n; i++)
{
vis[i] =0;
dist[i] =-INF;
}
dist[src] =0;
int Q[maxn *3], top =1;
Q[0] = src;
vis[src] =true;
while (top)
{
int u, v;
u = Q[--top];
vis[u] =false;
for (i = head[u]; i !=-1; i = nxt[i])
{
v = pnt[i];
if (1== relax(u, v, cost[i]) &&!vis[v])
{
Q[top++] = v;
vis[v] =true;
}
}
}
return dist[n];
}
void input()
{
mmax =0;
mmin = INF;
for (int i =0; i < n; i++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
a++;
b++;
if (mmax < b)
mmax = b;
if (mmin > a)
mmin = a;
addedge(a -1, b, c);
}
for (int i = mmin; i <= mmax; i++)
{
addedge(i, i -1, -1);
addedge(i -1, i, 0);
}
}
int main()
{
//freopen("t.txt", "r", stdin);
scanf("%d", &n);
e =0;
memset(head, -1, sizeof(head));
input();
printf("%d\n", SPFA(mmin -1, mmax));
return0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
usingnamespace std;
#define maxn 50005
#define INF 0x3f3f3f3f
int pnt[maxn *3], cost[maxn *3], nxt[maxn *3];
int e, head[maxn];
int dist[maxn];
bool vis[maxn];
int n, mmin, mmax;
int relax(int u, int v, int c)
{
if (dist[v] < dist[u] + c)
{
dist[v] = dist[u] + c;
return1;
}
return0;
}
inline void addedge(int u, int v, int c)
{
pnt[e] = v;
cost[e] = c;
nxt[e] = head[u];
head[u] = e++;
}
int SPFA(int src, int n)
{
int i;
for (i = src; i <= n; i++)
{
vis[i] =0;
dist[i] =-INF;
}
dist[src] =0;
int Q[maxn *3], top =1;
Q[0] = src;
vis[src] =true;
while (top)
{
int u, v;
u = Q[--top];
vis[u] =false;
for (i = head[u]; i !=-1; i = nxt[i])
{
v = pnt[i];
if (1== relax(u, v, cost[i]) &&!vis[v])
{
Q[top++] = v;
vis[v] =true;
}
}
}
return dist[n];
}
void input()
{
mmax =0;
mmin = INF;
for (int i =0; i < n; i++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
a++;
b++;
if (mmax < b)
mmax = b;
if (mmin > a)
mmin = a;
addedge(a -1, b, c);
}
for (int i = mmin; i <= mmax; i++)
{
addedge(i, i -1, -1);
addedge(i -1, i, 0);
}
}
int main()
{
//freopen("t.txt", "r", stdin);
scanf("%d", &n);
e =0;
memset(head, -1, sizeof(head));
input();
printf("%d\n", SPFA(mmin -1, mmax));
return0;
}