参照网上的约束条件,设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;
}
posted on 2011-08-02 18:58  NKHe!!oWor!d  阅读(290)  评论(0编辑  收藏  举报