Intervals

这题依然 SPFA + 栈 过!

不同的是,这题有隐含条件,而且所求也大不一样。

由于这是对区间操作,求至少包含区间[ai, bi]中ci个点的最小集合。可以用集合元素个数来定义变量,即num[bi] - num[ai] >= ci, 但有个隐含条件就是,每个元素都是整点,取得话,最多为一,最少为0, 即 num[i+1] - num[i] <= 1, num[i+1] - num[i] >= 0, 将这些条件再转换成最短路里的边和权,就可以做了。

这里求得是至少,也就是最小值,即 num[maxn] - num[0] >= ans, 我们要转化成 <= 号,也就是 num[0] - num[maxn] <= -ans, 这样就行了,赋初值时,令dis[maxn] = 0,求得就是每个点到maxn的距离了,输出结果就是dis[0]加个负号。

 

代码
#include<stdio.h>
#include
<stdlib.h>
#define INF 0xfffffff
#define NN 50004
#define MM 150004
int edNum, maxn;
int mark[NN];
int root[NN];
int dis[NN];
int next[MM];
int stack[NN];
struct node{
int e, v;
}edge[MM];

void Init(){
int i;
for (i = 0; i < NN; i++){
mark[i]
= 0;
root[i]
= -1;
dis[i]
= INF;
}
}

void add(int a, int b, int c){
edge[edNum].e
= b;
edge[edNum].v
= c;
next[edNum]
= root[a];
root[a]
= edNum++;
}

void Spfa()
{
int i, cur, nxt, tmp, top = 0;
for (i = 0; i <= maxn; i++){
if (root[i] != -1){
stack[
++top] = i;
mark[i]
= 1;
}
}
// 这里需要注意,要将终点置零,求的就是别的点到终点maxn的距离
dis[maxn] = 0;
while (top){
cur
= stack[top--];
mark[cur]
= 0;
tmp
= root[cur];
while (tmp != -1){
nxt
= edge[tmp].e;
if (dis[nxt] > dis[cur] + edge[tmp].v){
dis[nxt]
= dis[cur] + edge[tmp].v;
if (!mark[nxt]){
mark[nxt]
= 1;
stack[
++top] = nxt;
}
}
tmp
= next[tmp];
}
}
}
int main()
{
int n, i, a, b, c;
scanf(
"%d", &n);
maxn
= 0;
edNum
= 0;
Init();
for (i = 1; i <= n; i++){
scanf(
"%d%d%d", &a, &b, &c);
add(b
+ 1, a, -c);
if (b + 1 > maxn){
maxn
= b + 1;
}
}
for (i = 0; i <= maxn; i++){
add(i
+ 1, i, 0);
add(i, i
+ 1, 1);
}
Spfa();
//输出的时候也要注意,是起点到终点的距离的负值
printf("%d\n", -dis[0]);
// system("pause");
return 0;
}

 

posted on 2010-07-23 13:17  ylfdrib  阅读(351)  评论(0编辑  收藏  举报