【问题描述】
有一个整数序列,他的每个数各不相同,我们不知道他的长度是多少(序列中整数的个数)。但我们知道某些区间中至少有多少个整数,用三个参数:Li,Ri,Ci来描述,其意义表示这个整数序列中至少有Ci个数来至区间[Li,Ri],给出若干个这样的信息,问这个整数序列的长度最少能为多少?
【输入格式】
第一行一个整数N,表示给出的信息条数;
接下来N行,每行三个整数:Li,Ri,Ci,其意义如题目所叙!。
【输出格式】
仅一个整数,表示该区间整数序列最小长度。
【输入样例】
4
4 5 1
6 10 3
7 10 3
5 6 1
【输出样例】
4
【数据范围】
N<=50000,0<=Li<=Ri<=50000 , 1<=Ci<=Ri-Li+1
【来源】
poj 1201
简单来说这道题的意思就是d[li-1]指向d[ri]一条长度为ci的边,可以用差分约束来做,但要注意几点.
1.每一个点可以指向他下一个点一条长度为0的边。
2.每个点可以指向前一个点一条长度为-1的边。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int maxn=50005;
const int inf=200000000;
vector<int>g[maxn],w[maxn];
int d[maxn],q[maxn*100],vis[maxn]={0};
int n=0,m;
void init()
{
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
g[x-1].push_back(y);
w[x-1].push_back(z);
n=max(n,y);
}
for(int i=1;i<=n;i++)
{
g[i-1].push_back(i);
w[i-1].push_back(0);
g[i].push_back(i-1);
w[i].push_back(-1);
}
}
void in()
{
for(int i=0;i<=n;i++)
d[i]=-inf;
}
void spfa()
{
int root=0,front=0;
q[root++]=0;
vis[0]=1;
d[0]=0;
while(root!=front)
{
int i=q[front++];
vis[i]=0;
for(int k=0;k<g[i].size();k++)
{
int j=g[i][k],c=w[i][k];
if(d[i]+c<=d[j]) continue;
d[j]=d[i]+c;
if(vis[j]) continue;
q[root++]=j;
vis[j]=1;
}
}
}
int main()
{
init();
in();
spfa();
printf("%d\n",d[n]);
return 0;
}