题目看去有点难下手,如果学习了差分约束系统或是贪心算法会觉得很简单。
刚开始时用Bellman-Ford算法解,采用的是求最短路径,由于Bellman-Ford算法复杂度本身就高,再加上增设了m+1条边,时间复杂度就更高了,所依超时了,后来改用求最大路径,不用增设源节点,这样就省时多了。提交后用时两百多毫秒,还算快。然后用SPFA算法再写了一遍,算是开拓思路,温习算法吧,用时32ms。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=10002;
int m,num,dist[maxn];
struct Edge
{
int s;
int t;
int w;
}edge[5*maxn];
void Bellman_Ford()
{
int i;
bool flag=true;
while(flag)
{
flag=false;
for(i=0;i<num;i++)
if(dist[edge[i].t]<dist[edge[i].s]+edge[i].w)
{
dist[edge[i].t]=dist[edge[i].s]+edge[i].w;
flag=true;
}
}
}
int main()
{
int i,n,a,b;
while(scanf("%d",&n)!=EOF)
{
num=0;
scanf("%d%d",&a,&b);
edge[num].s=a;
edge[num].t=b+1;
edge[num++].w=2;
m=b+1;
for(i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
edge[num].s=a;
edge[num].t=b+1;
edge[num++].w=2;
if(b+1>m)
m=b+1;
}
for(i=0;i<m;i++)
{
edge[num].s=i;
edge[num].t=i+1;
edge[num++].w=0;
edge[num].s=i+1;
edge[num].t=i;
edge[num++].w=-1;
}
memset(dist,0,sizeof(dist));
Bellman_Ford();
printf("%d\n",dist[m]-dist[0]);
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#define inf 10000000
using namespace std;
const int maxn=10006;
int m,num,dist[maxn],visit[maxn],head[maxn],queue[50*maxn]; //visit数组标志该结点是在队列外还是队列内
struct Edge
{
int t; //终点
int w;
int next; //下一条边的标号
}edge[8*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,j,u,v,id,first,last;
first=0;
last=0;
visit[m+1]=true;
dist[m+1]=0;
queue[last++]=m+1; //将源结点压入队列中
while(first!=last)
{
u=queue[first++];
visit[u]=false; //结点出队,所以要置为false
id=head[u]; //取出以结点u为起点的邻接表的表头,即第一条边的标号
while(id!=-1)
{
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; //值为false的结点没有入队,值为true的入队了
queue[last++]=v;
}
}
id=edge[id].next; //取邻接表的下一条边
}
}
}
int main()
{
int i,j,n,a,b;
while(scanf("%d",&n)!=EOF)
{
memset(head,-1,sizeof(head)); //开始时所有头结点都指向表尾
num=0;
m=-1;
for(i=0;i<n;i++)
{
scanf("%d%d",&a,&b);
if(b+1>m)
m=b+1;
addEdge(b+1,a,-2);
}
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;
}