通过这道题又进一步理解了SPFA和差分约束
我们求最最短路径是 通过松弛(if(dis[end] > dis[start] + cost[start][end])所求出来的所有点满足 dis[end] <= dis[start] + cost[start][end]
而差分约束条件求解满足 所有 a - b <= c i 的 c 最小值 ,转换一下 a <= ci +b 这正好是SPFA松弛之后所满足的条件;
此题有b - a + 1 >= ci 我们转换下SPFA的松弛条件, 使得(if(dis[end] < dis[start] + cost[start][end] 那么dis[end] >= dis[start] + cost[start][end]
另外题中有两个隐含条件 ai+1 - ai <= 1 ai+i - ai >= 0 (如果要用ai-1-ai<=1 ai+1 - ai >=0 的话要注意 i 的值可能会为零,这就好做一个下标平移输入时+1即可)
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
#define INF -10000
#define MAX 50000
using namespace std;
int maxn,minn;
int num = 0;
int head[MAX+10];
int vis[MAX+10];
int dis[MAX+10];
struct Edeg
{
int v;
int w;
int next;
}edge[MAX*3];
int spfa()
{
queue<int>Q;
for(int i=minn; i<=maxn+1; i++)
dis[i]=INF;
dis[minn]=0;
memset(vis,false,sizeof(vis));
vis[minn]=true;
Q.push(minn);
while(!Q.empty())
{
int x=Q.front();
Q.pop();
vis[x]=false;
for(int i=head[x]; i!=-1; i=edge[i].next)
{
if(dis[edge[i].v]<dis[x]+edge[i].w)
{
dis[edge[i].v]=dis[x]+edge[i].w;
if(!vis[edge[i].v])
{
vis[edge[i].v]=true;
Q.push(edge[i].v);
}
}
}
}
return dis[maxn];
}
void add(int u,int v,int w)
{
edge[num].v=v;
edge[num].w=w;
edge[num].next=head[u];
head[u]=num++;
}
int main()
{
int n;
int a,b,c;
while(scanf("%d",&n)!=EOF)
{
num = 0;
memset(head,-1,sizeof(head));
minn = -INF;
maxn = 0;
while(n--)
{
scanf("%d%d%d",&a, &b, &c);
//下标平移
//a++ ; b++;
add(a,b+1,c);
if(minn > a)
minn = a;
if(maxn < b+1)
maxn = b+1;
}
for(int i=minn;i<maxn;i++)
{
add(i,i+1,0);
add(i+1,i,-1);
}
printf("%d\n",spfa());
}
return 0;
}