参照网上的约束条件,设d[i]为[0,i)区间内需要取的元素个数,则条件有:对于每个[ai,bi],d[bi]-d[ai-1] >=2; 0=<d[i]-d[i-1]<=1,d[0]=0;当全部归为>=时求最长路,<=时求最短路。本题可以以0为源点求最短路,原因我还没理解。为保险起见,也是我的习惯,设置一个超级源点,到每个点都有一条边,权值为0.结果这样做时间反而比直接以0为源点还要快200ms,至今无法解释。。。第一个版本用vector和queue写的,时间都在900+,甚至有一次幸运的卡在了1000ms。改掉queue,时间基本不变,改掉vector,时间瞬间缩短至<32ms,看来这个vector确实够慢啊。。。方便但是不保险。。。以后比赛时还是手写一下吧。另外本题需要注意数组不要开小了。
至今未解之谜:
1.为何加入超级源来做比以0为源的做法,能快200ms
2.为何所有dis的初值应该<=-1,而设为0就会WA,以后求最长路都应该设为-oo最保险。
两个版本的代码:
一、STL:
//9062543 NKHelloWorld 1716 Accepted 1380K 969MS G++ 1465B 2011-08-02 17:16:25
//9062918 NKHelloWorld 1716 Accepted 996K 954MS C++ 1545B 2011-08-02 18:06:15
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
int n,maxb = 0,dis[11000];
struct EDGE
{
int from,to,d;
};
vector<EDGE> edge[11000];
int spfa(int s)
{
int i,a,b,d;
bool inque[11000];
queue<int> que;
for(i=0;i<=maxb;i++)
{
inque[i] = false;
dis[i] = -2147483647;
}
dis[s] = 0;
inque[s] = true;
que.push(s);
while(!que.empty())
{
a = que.front();
inque[a] = false;
que.pop();
for(i=0;i<edge[a].size();i++)
{
b = edge[a][i].to;
d = edge[a][i].d;
if(dis[b] < dis[a]+d)
{
dis[b] = dis[a]+d;
if(inque[b]==false)
que.push(b);
}
}
}
return 0;
}
int main()
{
int i,j,a,b,d = 2;
EDGE now;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
now.from = a; now.to = b+1; now.d = d;
if(now.to > maxb)
maxb = now.to;
edge[now.from].push_back(now);
}
for(i=1;i<=maxb;i++)
{
now.from = i; now.to = i-1; now.d = -1;
edge[now.from].push_back(now);
now.from = i-1; now.to = i; now.d = 0;
edge[now.from].push_back(now);
}
spfa(0);
printf("%d\n",dis[maxb]-dis[0]);
//for(i=0;i<=maxb;i++)printf("%d ",dis[i]);
return 0;
}
二、手写队列,临接表:
//9063108 NKHelloWorld 1716 Accepted 6700K 47MS C++ 2051B 2011-08-02 18:35:47
//9063087 NKHelloWorld 1716 Accepted 6700K 47MS C++ 2052B 2011-08-02 18:33:08
//9063134 NKHelloWorld 1716 Accepted 2276K 0MS C++ 1736B 2011-08-02 18:39:59
#include <cstdio>
using namespace std;
int n,maxb = 0,dis[11000];
struct EDGE
{
int from,to,d;
};
EDGE edge[11000][15];
int pedge[11000];
int spfa(int s)
{
int i,a,b,d;
bool inque[11000];
int que[31000],tail = 0,head = 0;
for(i=0;i<=maxb;i++)
{
inque[i] = false;
dis[i] = -2147483647;
}
dis[s] = 0;
inque[s] = true;
que[tail++] = s;
while(head<tail)
{
a = que[head];
inque[a] = false;
head++;
for(i=0;i<pedge[a];i++)
{
b = edge[a][i].to;
d = edge[a][i].d;
if(dis[b] < dis[a]+d)
{
dis[b] = dis[a]+d;
if(inque[b]==false)
que[tail++] = b;
}
}
}
return 0;
}
int main()
{
int i,j,a,b,d = 2;
EDGE now;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
now.from = a; now.to = b+1; now.d = d;
if(now.to > maxb)
maxb = now.to;
edge[a][pedge[a]++] = now;
}
for(i=1;i<=maxb;i++)
{
now.from = i; now.to = i-1; now.d = -1;
edge[now.from][pedge[now.from]++] = now;
now.from = i-1; now.to = i; now.d = 0;
edge[now.from][pedge[now.from]++] = now;
}
for(i=0;i<=maxb;i++)
{
now.from = maxb+1; now.to = i; now.d = 0;
edge[now.from][pedge[now.from]++] = now;
}
spfa(maxb+1);
printf("%d\n",dis[maxb]-dis[0]);
return 0;
}