poj1201

题意:给定一些区间和每个区间内的元素数量(选一些互不相同的整数作为区间内的元素,每个整数只至多选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;
}
原文地址:https://www.cnblogs.com/rainydays/p/2088222.html