【POJ1201】Intervals【差分约束】
题目大意:
题目链接:http://poj.org/problem?id=1201
从中选择尽量少的数字使得组形如“到中选择的数字不少于个”的要求全部满足。
思路:
设表示从中选择的数字个数。那么对于任意一个要求,都需要满足,与差分约束十分相像。于是从连向一条长度为的边。
同时我们对于数字,肯定是要么选择,要么不选。所以本题中还有两个隐含条件,。
对于条件1,可以直接从向连一条长度为0的边,对于条件2,变形得,从向连一条长度为-1的边。
由于不等式符号全部是大于,所以需要跑最长路。很明显图中是不含正环的,所以可以不用判正环。以-1为源点跑即可。答案即为。
但是下标是不可以用负数的。所以可以把所有点的下标+1,变成“从”中选择,从0开始跑,答案就是。
代码:
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N=50010;
int n,x,y,z,tot,head[N],dis[N];
bool vis[N];
struct edge
{
int next,to,dis;
}e[N*3];
void add(int from,int to,int dis)
{
e[++tot].to=to;
e[tot].dis=dis;
e[tot].next=head[from];
head[from]=tot;
}
void spfa()
{
memset(dis,0xcf,sizeof(dis));
queue<int> q;
q.push(0);
dis[0]=0;
vis[0]=1;
while (q.size())
{
int u=q.front(),v;
q.pop();
vis[u]=0;
for (int i=head[u];~i;i=e[i].next)
{
v=e[i].to;
if (dis[v]<dis[u]+e[i].dis)
{
dis[v]=dis[u]+e[i].dis;
if (!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x+1,y+2,z);
}
for (int i=1;i<=50001;i++)
add(i-1,i,0),add(i,i-1,-1);
spfa();
printf("%d\n",dis[50001]);
return 0;
}