dijks

堆优化

复杂度nlogn

type hhh=record
   z,w:longint;
end;
var cnt,i,j,k,a,b,ge,n,m,x,c:longint;//刚开始领接表数据开小了
    d:array[0..500000]of longint;
    heap:array[-10..500090]of hhh;
    vist:array[0..500900]of boolean;
    pre,head,v,w:array[0..500009]of longint;

procedure add(a,b,c:longint);
begin
 inc(cnt);v[cnt]:=b;w[cnt]:=c;pre[cnt]:=head[a];head[a]:=cnt;end;
procedure jia(a:longint);
var i:longint;
    j:hhh;
begin
 inc(ge);
 i:=ge;
 heap[ge].z:=d[a];
 heap[ge].w:=a;
 while (i div 2)<>0 do
  if heap[i].z<heap[i div 2].z then begin

    j:=heap[i];
    heap[i]:=heap[i div 2];
    heap[i div 2]:=j;
    i:=i div 2;
end
 else break;
end;


procedure jian;
var min,i,k:longint;
    j:hhh;
begin
  heap[1]:=heap[ge];
  dec(ge);
  i:=1;k:=i*2;
  while (k)<=ge do
begin
 if(k+1<=ge) and (heap[k+1].z<heap[k].z) then inc(k);
 if heap[k].z>heap[i].z then break
 else begin j:=heap[k];heap[k]:=heap[i];heap[i]:=j;end;
 i:=K;K:=I*2;
end;
end;



procedure dijks(a:longint);
var i,j,k,min,t,p,vv:longint;
begin
 for i:=1 to n do d[i]:=100000000;
 fillchar(vist,sizeof(vist),false);
 d[a]:=0;
 jia(a);
while ge>0 do
 begin
  t:=heap[1].w;
  k:=heap[1].z;
  if vist[t] then begin jian;continue;end;//排除重边的干扰
 vist[t]:=true;
 jian;
 j:=head[t];
while j>0 do
begin
 vv:=v[j];
  if  (d[vv]>k+w[j])and(not vist[vv]) then//可能重边
  begin
   d[vv]:=k+w[j];
   jia(vv);
end; 
j:=pre[j];
end;
end;
end;



begin
 readln(n,m,x);
 for j:=1 to m do
 begin
  readln(a,b,c);
 if a=b then continue;
 add(a,b,c);
end;
 dijks(x);
 for j:=1 to n do begin if d[j]=100000000 then write(2147483647,' ')
 else write(d[j],' ');end;
   end .

非递归线段树 有时间好好看 顺便把他改成递归型

#include<cstdio>
#include<cstring>
#include<algorithm> 
using namespace std;
const int maxn =10007;
const int maxm = 500007;
const int INF = 0x7fffffff;
int n,m;
inline int read() {
    int x=0;
    char c=getchar();
    while(c<'0'||c>'9') 
        c=getchar();
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x;
}
struct node{
    int v,next,w;
}edge[maxm];
int num=0,head[maxn];
inline void add_edge(int a,int b,int c) {
    edge[++num].v=b;edge[num].w=c;edge[num].next=head[a];head[a]=num;
} 
int dis[maxn],ans[maxn],s,t;
int tree[maxn<<2],leaf;
inline int check(int i,int j) {
    return dis[i]<dis[j]?i:j;
 } 
inline void build() {
    std::memset(dis,0x3f,sizeof dis);// for(int i=0;i<=n+1;i++) dis[i]=INF;
    for(leaf=1;leaf<=n;leaf<<=1);--leaf;
    for(int i=1;i<=n;++i)tree[leaf+i]=i;
}
inline void modify(int x,int y) {
    dis[x]=y,x+=leaf,x>>=1;
    while(x) tree[x]=check(tree[x<<1],tree[x<<1|1]),x=x>>1;
}
void dijkstra(int s) {
    build();
    dis[s]=0;
    int u=s;
    for(int i=1;i<=n;++i) {
        ans[u]=dis[u];
        const int disu=dis[u];
        modify(u,INF); 
        for(int j=head[u];j;j=edge[j].next){
              int v=edge[j].v;
              if(dis[v]<INF&&dis[v]>disu+edge[j].w)
                modify(v,disu+edge[j].w);
        }
        u=tree[1];
      }
}
inline void put(int x)
{
    if (x > 9) put(x / 10);
    putchar(x % 10 + 48);   
}

int main() {
    int k;
    n=read(),m=read(),k=read();
    for(int a,b,c,i=1;i<=m;++i) {
        a=read(),b=read(),c=read();
        add_edge(a,b,c);
    }
    dijkstra(k);
    for(int i=1;i<=n;++i) {
        if(dis[i]==0x3f3f3f3f)ans[i]=INF;
       // put(ans[i]), putchar(' ');
        printf("%d ",ans[i]);
    }
    return 0;
}
 

 

posted @ 2018-08-09 20:02  谨川  阅读(260)  评论(0编辑  收藏  举报