题目很简单,用差分约束系统解决。假设Si=Z与结合[1,i)的交集的元素的个数,则依题意有S[b+1]-S[a]>=c,还有隐含条件S[i+1]-S[i]>=0 && S[i]-S[i+1]>=-1。然后求最短路径或最长路径,用Bellman-Ford算法解会超时,于是用SPFA算法解,288ms,还算快。
可以通过SPFA算法求最短路,也可以通过SPFA算法求最长路解这题,时间消耗上差不多一样的。为什么可以求最长路了?
记住一句话:求最小值,>=,求最长路;求最大值,<=,求最短路。为什么可以上网查找,只要理解了差分约束系统和SPFA算法就很容易理解。
//求最短路径
#include <iostream>
#include <cstdio>
#include <cstring>
#define inf 100000000
using namespace std;
const int maxn=50010;
int num,m,head[maxn],dist[maxn],queue[50*maxn];
bool visit[maxn];
struct Edge
{
int t;
int w;
int next;
}edge[6*maxn];
void addEdge(int s,int t,int w)
{
edge[num].t=t;
edge[num].w=w;
edge[num].next=head[s];
head[s]=num++;
}
void SPFA()
{
int i,u,v,id,first,last;
first=0;
last=0;
visit[m+1]=true; //源结点m+1入队
dist[m+1]=0;
queue[last++]=m+1;
while(first!=last)
{
u=queue[first++];
id=head[u];
visit[u]=false; //结点u出了队,就标志为false
while(id!=-1) //访问结点u的邻接表
{
v=edge[id].t;
if(dist[u]+edge[id].w<dist[v] || dist[v]==inf)
{
dist[v]=dist[u]+edge[id].w;
if(!visit[v]) //如果更新的结点不再队列里,则入队
{
visit[v]=true;
queue[last++]=v;
}
}
id=edge[id].next;
}
}
}
int main()
{
int i,j,n,a,b,c;
while(scanf("%d",&n)!=EOF)
{
memset(head,-1,sizeof(head));
m=-1;
for(i=0;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(m<b+1)
m=b+1;
addEdge(b+1,a,-c);
}
for(i=0;i<=m;i++)
addEdge(m+1,i,0); //增加源结点m+1
for(i=0;i<m;i++)
{
addEdge(i,i+1,1);
addEdge(i+1,i,0);
}
memset(visit,0,sizeof(visit));
for(i=0;i<=m+1;i++)
dist[i]=inf;
SPFA();
printf("%d\n",dist[m]-dist[0]);
}
return 0;
}
//求最长路径
#include <iostream>
#include <cstdio>
#include <cstring>
#define inf -100000000
using namespace std;
const int maxn=50010;
bool visit[maxn];
int m,num,dist[maxn],head[maxn],queue[50*maxn];
struct Edge
{
int t;
int w;
int next;
}edge[6*maxn];
void addEdge(int s,int t,int w)
{
edge[num].t=t;
edge[num].w=w;
edge[num].next=head[s];
head[s]=num++;
}
void SPFA()
{
int i,u,v,id,first,last;
first=0;
last=0;
queue[last++]=0; //源结点设为0
dist[0]=0;
visit[0]=true;
while(first!=last)
{
u=queue[first++];
id=head[u];
visit[u]=false;
while(id!=-1)
{
v=edge[id].t;
if(dist[v]<dist[u]+edge[id].w || dist[v]==inf)
{
dist[v]=dist[u]+edge[id].w;
if(!visit[v])
{
visit[v]=true;
queue[last++]=v;
}
}
id=edge[id].next;
}
}
}
int main()
{
int i,n,a,b,c;
while(scanf("%d",&n)!=EOF)
{
num=0;
memset(head,-1,sizeof(head));
m=-1;
for(i=0;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(m<b+1)
m=b+1;
addEdge(a,b+1,c);
}
for(i=0;i<m;i++)
{
addEdge(i+1,i,-1);
addEdge(i,i+1,0);
}
memset(visit,0,sizeof(visit));
for(i=0;i<=m;i++)
dist[i]=inf;
SPFA();
printf("%d\n",dist[m]-dist[0]);
}
return 0;
}