参照网上的约束条件,设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; }