题目点击打开链接
差分约束
根据题意我们可以列出多组不等式
① f(b1+1)-f(a1)>=c1,
f(b2+1)-f(a2)>=c2
...
f(bn+1)-f(an)>=cn
所以可以建边(ai,bi+1,ci)
②同时我们要发现隐含的约束条件:
f(i)-f(i-1)>=0
f(i)-f(i-1)<=1移向后变为f(i-1)-f(i)>=-1
所以可建边(i-1,i,0)
(i,i-1,-1)
③最后用SPFA求一下最大路径(根据建边的方式(移向的方式)选择求最大路径或最小路径,本质一样,结果互为相反数
代码如下:
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define _(d) while(d (((ch=getchar())>47)&&ch<58))
using namespace std;
const int MaxN=50005;
const int Maxe=MaxN<<3;
const int inf=0x7fffffff;
int n,tt,mx,mn,d[MaxN],h[MaxN],to[Maxe],s[Maxe],nxt[Maxe];
bool vst[MaxN];
inline void Get(int &x){char ch;_(!);x=ch-48;_()x=(x<<3)+(x<<1)+ch-48;}
inline void add(int u,int v,int c)
{
to[++tt]=v;s[tt]=c;nxt[tt]=h[u];h[u]=tt;
}
queue<int> q;
inline void spfa()
{
for(int i=0;i<MaxN;i++) vst[i]=0,d[i]=-inf;//init
q.push(mn);
vst[mn]=1;
d[mn]=0;
int u;
while(!q.empty())
{
u=q.front();q.pop();vst[u]=0;//invoke
for(int i=h[u];i;i=nxt[i])
{
int v=to[i];
if(d[v]<d[u]+s[i])
{
d[v]=d[u]+s[i];//loosen
if(!vst[v])//make it in queue
{
q.push(v);
vst[v]=1;
}
}
}
}
}
int main()
{
freopen("1534.in","r",stdin);
int a,b,c;
Get(n);
for(int i=1;i<=n;i++)
{
Get(a);Get(b);Get(c);
mx=max(mx,b+1);
mn=min(mn,a);
add(a,b+1,c);
}
for(int i=mn;i<=mx;i++)
{
add(i,i-1,-1);
add(i-1,i,0);
}
spfa();
printf("%d\n",d[mx]);
return 0;
}
)