讨论 / [PID 606 NOI2010 海拔]管理员看一眼呐……求时限……求放过……
fts96 2012-10-14 00:44:00
点我顶贴 收藏 删除
实在是没办法了……过不去……永远卡第九个点……

写了三天多了……Pascal和C++分别写了spfa和dijkstra+heap……

cena手测c++最大点0.82s……pascal最大0.57s……tyvj最大点443ms……该算是过了吧……

实在不行了……求放过吧……开点时限什么的……

水平就这样了……求神牛优化……

pascal:

program heap_dijkstra;

const maxn=250010;

maxm=1200000;

inf=100000000;

type

ed=record

t,w,next:longint;

end;

heap_type=record

v,d:longint;

end;

var

heap:array[0..maxn] of heap_type;

edge:array[1..maxm] of ed;

hpos,box:array[1..maxn] of longint;

n,m,sum,hl:longint;

procedure add_edge(s,t,w:longint);

begin

inc(sum);

edge[sum].t:=t;

edge[sum].w:=w;

edge[sum].next:=box[s];

box[s]:=sum;

end;

procedure build_graph;

var i,j,w:longint;

begin

readln(n);

for i:=1 to n+1 do

begin

for j:=1 to n do

begin

read(w);

if i=1 then add_edge(n*n+1,j,w)

else if i=n+1 then add_edge((i-2)*n+j,n*n+2,w)

else add_edge((i-2)*n+j,(i-1)*n+j,w);

end;

end;

for i:=1 to n do

begin

for j:=1 to n+1 do

begin

read(w);

if j=1 then add_edge((i-1)*n+1,n*n+2,w)

else if j=n+1 then add_edge(n*n+1,i*n,w)

else add_edge((i-1)*n+j,(i-1)*n+j-1,w);

end;

end;

for i:=1 to n+1 do

begin

for j:=1 to n do

begin

read(w);

if i=1 then add_edge(j,n*n+1,w)

else if i=n+1 then add_edge(n*n+2,(i-2)*n+j,w)

else add_edge((i-1)*n+j,(i-2)*n+j,w);

end;

end;

for i:=1 to n do

begin

for j:=1 to n+1 do

begin

read(w);

if j=1 then add_edge(n*n+2,(i-1)*n+1,w)

else if j=n+1 then add_edge(i*n,n*n+1,w)

else add_edge((i-1)*n+j-1,(i-1)*n+j,w);

end;

end;

n:=n*n+2;

end;

{procedure build_graph;

var i:longint;

s,t,w:longint;

begin

readln(n,m);

for i:=1 to m do

begin

readln(s,t,w);

add_edge(s,t,w);

add_edge(t,s,w);

end;

end; }

procedure swap(a,b:longint);

begin

heap[0]:=heap[a];heap[a]:=heap[b];heap[b]:=heap[0];

hpos[heap[a].v]:=a;hpos[heap[b].v]:=b;

end;

procedure decrease(x:longint);

var i:longint;

begin

i:=x;

while (i<>1)and(heap[i].d<heap[i div 2].d) do

begin

swap(i,i div 2);

i:=i div 2;

end;

end;

procedure heapify;

var

i:longint;

begin

i:=2;

while i<=hl do

begin

if (i<hl)and(heap[i+1].d<heap[i].d) then inc(i);

if heap[i].d<heap[i div 2].d then

begin

swap(i,i div 2);

i:=i*2;

end

else break;

end;

end;

procedure relax(v,u,w:longint);

begin

if w+heap[hpos[v]].d<heap[hpos[u]].d then

begin

heap[hpos[u]].d:=heap[hpos[v]].d+w;

decrease(hpos[u]);

end;

end;

procedure dijkstra(s:longint);

var v,i,u:longint;

p:longint;

begin

for i:=1 to n do

begin

heap[i].v:=i;

heap[i].d:=inf;

hpos[i]:=i;

end;

heap[s].d:=0;

swap(1,s);

hl:=n;

while (hl>0)and(hpos[n]<=hl) do

begin

v:=heap[1].v;

swap(1,hl);

dec(hl);

heapify;

p:=box[v];

while p>0 do

begin

if hpos[edge[p].t]<=hl then relax(v,edge[p].t,edge[p].w);

p:=edge[p].next;

end;

end;

end;

begin

assign(input,'in.txt');

reset(input);

assign(output,'out.txt');

rewrite(output);

build_graph;

dijkstra(n-1);

writeln(heap[hpos[n]].d);

close(input);

close(output);

end.

c++:

#include <stdio.h>

#include <iostream>

#include <stdlib.h>

#define MAXN 250010

#define MAXM 1200000

#define inf 200000000

using namespace std;

int t[MAXM],w[MAXM],nex[MAXM],d[MAXN],v[MAXN],hpos[MAXN],box[MAXN];/*q[MAXN+1],then[MAXN+1],befo[MAXN+1],flag[MAXN+1],box[MAXN+1],dis[MAXN+1]*/

int sum,n,head,tail,i,hl;

void add_edge(int ss,int tt,int ww)

{

t[++sum]=tt;

w[sum]=ww;

nex[sum]=box[ss];

box[ss]=sum;

}

void init()

{

int i,j,ww;

sum=0;

scanf("%d",&n);

for (i=2;i<MAXN;++i)

{

d[i]=0;

box[i]=0;

}

box[1]=0;box[MAXN]=0;

for (i=1;i<=n+1;++i)

{

for (j=1;j<=n;++j)

{

scanf("%d",&ww);

if (i==1) add_edge(n*n+1,j,ww);

else if (i==n+1) add_edge((i-2)*n+j,n*n+2,ww);

else add_edge((i-2)*n+j,(i-1)*n+j,ww);

}

}

for (i=1;i<=n;++i)

{

for (j=1;j<=n+1;++j)

{

scanf("%d",&ww);

if (j==1) add_edge((i-1)*n+1,n*n+2,ww);

else if (j==n+1) add_edge(n*n+1,i*n,ww);

else add_edge((i-1)*n+j,(i-1)*n+j-1,ww);

}

}

for (i=1;i<=n+1;++i)

{

for (j=1;j<=n;++j)

{

scanf("%d",&ww);

if (i==1) add_edge(j,n*n+1,ww);

else if (i==n+1) add_edge(n*n+2,(i-2)*n+j,ww);

else add_edge((i-1)*n+j,(i-2)*n+j,ww);

}

}

for (i=1;i<=n;++i)

{

for (j=1;j<=n+1;++j)

{

scanf("%d",&ww);

if (j==1) add_edge(n*n+2,(i-1)*n+1,ww);

else if (j==n+1) add_edge(i*n,n*n+1,ww);

else add_edge((i-1)*n+j-1,(i-1)*n+j,ww);

}

}

n=n*n+2;

}

void swap(int a,int b)

{

d[0]=d[a];d[a]=d[b];d[b]=d[0];

v[0]=v[a];v[a]=v[b];v[b]=v[0];

hpos[v[a]]=a;hpos[v[b]]=b;

}

void decrease(int x)

{

int i;

i=x;

while ((i!=1)&&(d[i]<d[i>>1]))

{

swap(i,i>>1);

i=i>>1;

}

}

void heapify()

{

int i=2;

while (i<=hl)

{

if ((i<hl)&&(d[i+1]<d[i])) ++i;

if (d[i]<d[i>>1])

{

swap(i,i>>1);

i*=2;

}

else break;

}

}

void relax(int u,int v,int w)

{

if (d[hpos[v]]>d[hpos[u]]+w)

{

d[hpos[v]]=d[hpos[u]]+w;

decrease(hpos[v]);

}

}

void dijkstra(int s)

{

int p,i,V,U;

for (i=1;i<=n;++i)

{

v[i]=i;

hpos[i]=i;

d[i]=inf;

}

d[hpos[s]]=0;

swap(1,s);

hl=n;

while ((hl)&&hpos[n]<=hl)

{

V=v[1];

swap(1,hl);

--hl;

heapify();

p=box[V];

while (p)

{

if (hpos[t[p]]<=hl) relax(V,t[p],w[p]);

p=nex[p];

}

}

printf("%d\n",d[hpos[n]]);

}

int main()

{

freopen("in.txt","r",stdin);

freopen("out.txt","w",stdout);

init();

dijkstra(n-1);

return 0;

}

#1 linjianyu@2012-10-12 20:43:00
回复 删除
回复 楼主fts96 的帖子

堆里最小的数是终点就直接退出,

我就pascal dijkstra+heap过的

#2 fts96@2012-10-12 22:05:00
回复 删除
[quote][url=/Redirect.asp?Act=Reply&DID=11615&RID=28463]原帖[/url]由 [i]linjianyu[/i] 于 2012-10-13 11:43:00 发表

堆里最小的数是终点就直接退出,

我就pascal dijkstra+heap过的[/quote]

while (hl>0)and(hpos[n]<=hl) do

这句话不就是这个意思么……但是依然TLE不止……

#3 linjianyu@2012-10-12 22:19:00
回复 删除
回复 板凳fts96 的帖子

多提交几次吧,rq的速度不比以前慢。

祝您初赛玩得开心。

#4 fts96@2012-10-13 03:10:00
回复 删除
回复 地毯linjianyu 的帖子

好吧……突然有用STL的优先队列试试的想法……

#5 fts96@2012-10-14 00:44:00
回复 删除
啊啊啊啊啊……实在写不下去了……

tyvj,cena手测均可1s内AC,求RQ时限开大或加快测评机速度……管理员看一眼呐……

查看更多回复
提交回复