题目链接:http://poj.org/problem?id=1201
题目大意:
给定n个区间[ai,bi]和区间范围内的整数个数ci,要求求出一个最小整数集合Z,使Z里面的数中在区间[ai,bi]的个数不小于ci个。
思路:
根据题意可以得出,
Sbi+1-Sai>=ci ->> Sai-Sbi+1<=-ci;
从而可以得出一组不等式组;
同时存在:
Si+1-Si<=1;
Si-Si+1<=0;
根据得出的不等式组构造图,求出区间最大端点max和最小端点min;
所求答案即为:dist[max+1]-dist[min];
#include<iostream>
using namespace std;
const int inf=1<<26;
class Edge
{
public:
int s;
int e;
int weight;
}edge[50005];
int dist[50005];
int edge_num;
int max_n;
int min_n;
bool bellman_ford()
{
int i,j;
bool flag=true;
for(i=1;i<=max_n;i++)
dist[i]=inf;
dist[0]=0;
while(flag)
{
flag=false;
for(j=1;j<=edge_num;j++)
{
if(dist[ edge[j].e ]>dist[ edge[j].s ]+edge[j].weight)
{
dist[ edge[j].e ]=dist[ edge[j].s ]+edge[j].weight;
flag=true;
}
}
for(j=min_n;j<=max_n;j++)
{
if(dist[j+1]>dist[j]+1)
{
dist[j+1]=dist[j]+1;
flag=true;
}
}
for(j=max_n;j>=min_n;j--)
{
if(dist[j]>dist[j+1])
{
dist[j]=dist[j+1];
flag=true;
}
}
}
return true;
}
int main()
{
while(~scanf("%d",&edge_num))
{
max_n=0;
min_n=inf;
int a,b,c;
for(int i=1;i<=edge_num;i++)
{
scanf("%d %d %d",&a,&b,&c);
edge[i].s=b+1;
edge[i].e=a;
edge[i].weight=-c;
if(max_n<b)
max_n=b;
if(min_n>a)
min_n=a;
}
bellman_ford();
printf("%d\n",dist[max_n+1]-dist[min_n]);
}
return 0;
}