差分約束就是把不等式似的的東西轉化爲最短路求解,格式是所有式子都是兩個未知數的差小於等於某個常數的就算,當然大於等於也可以,本題就是大於等於,乘-1就好~
1201題意:
[ai,bi]上至少要選擇ci個整數點,可以在區間內任意取不重複的點,問最少選多少個點,這麼些區間有重合部分,所以,列不等式啦
s[bi]-s[ai-1]>=ci
s[i]-s[i-1]<=1;
s[i]-s[i-1]>=0
據說一般差分約束系統是有負權邊的,所以用可以判斷的spfa
/*
Sbi - Sai >= ci
Si - Si-1 >= 0
Si-1 - Si >= -1
*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
#define maxN 50005
#define INF 1000000007
struct EDGE//使用鄰接表存邊
{
int v;
int cost;
int next;
}edge[3*maxN];
int first[maxN],d[maxN],visit[maxN];
int e,n,maxx,minn;
void AddEdge(int a,int b,int c)//添加新邊
{
edge[e].v=b;
edge[e].cost=c;
edge[e].next=first[a];
first[a]=e++;
}
void SPFA()
{
for(int i=minn;i<=maxx;i++)
d[i] = -INF;
d[minn] = 0;
queue<int>q;
q.push(minn);
while(!q.empty())
{
int x=q.front();
q.pop();
visit[x]=0;
for(int e=first[x];e!=-1;e=edge[e].next)
if(d[edge[e].v]<d[x]+edge[e].cost)
{
d[edge[e].v]=d[x]+edge[e].cost;
if(!visit[edge[e].v])
{
q.push(edge[e].v);
visit[edge[e].v]=1;
}
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int a,b,c;
e=0;
minn = INF;
maxx = -INF;
memset(first,-1,sizeof(first));
memset(visit,0,sizeof(visit));
memset(edge,0,sizeof(edge));
for(int i=0;i<n;i++)
{
scanf("%d%d%d", &a,&b,&c);//題目條件的邊
AddEdge(a,b+1,c);
minn=minn<a?minn:a;//在這裏記錄最小值和最大值
maxx=maxx>a+1?maxx:a+1;
}
for(int i=minn;i<maxx;i++)//添加新邊
{
AddEdge(i,i+1,0);
AddEdge(i+1,i,-1);
}
SPFA();
printf("%d\n",d[maxx]);
}
return 0;
}