poj 2449 Remmarguts' Date 第k最…

求第k最短路

这里要说的就比较多了,朴素的方法有两种实现的办法

1:spfa求,当把所有顶点的前k临时最短路都求出时,前k临时最短路就是确切的最短路,因为第k+1短路不能更新第k以内的最短路

2:dijkstra求,用宽搜实现该算法,第k次搜该顶点时,即为该顶点的第k最短路,因为是宽搜,所以保证后边的所有路径都比它长,因此该算法的正确性得到保证

但是前边两种做法都会tle

 

3:

网上流传的做法,启发式搜索

做反图,求最短路

然后f(n)=h(n)+g(n),反图的最短路就是g(n)

启发式搜索相比较于普通的宽搜的优点在于,有了估价函数的帮助,它会朝着目标搜索,而不是盲目的搜索

但是这样第一次搜索到的解怎么保证它是最优的呢?

首先,g(n)一定要小于等于离目标点的距离,那么当目标顶点出队列的时候,由于其他路径的更佳值都比该点的确切值差,那么他们的确切值最不可能超过它

至于启发式搜索的效率,这个不是那么好估计,等待以后弄明白了再补上

 

再啰嗦两句:关于堆的问题,这次是手写的堆,不过不得不说这个还是有点麻烦的,一来增加的了错误的可能性

,二来,这个有两个adjust函数,写起来也是要一点时间的

 

错误的地方:dijkstra写错了,起点更新的时候是直接更新的,这样对于起点自环会出错

 

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
int n,m;
struct node
{
    int to,dis;
    struct node *next;
}a[10010];

struct gt
{
    int to,dis;
    struct gt *next;
}b[10010];

struct node *p;
struct gt *q;
int d[10001],txt[10001];

int time[10001];

int dijs(int t,int n)
{
    for(int i=1;i<=n;i++)
    d[i]=inf;
    d[t]=0;
    for(int i=2;i<=n;i++)
    {
        int ted=inf,tmp=n+1;
        for(int j=1;j<=n;j++)
        {
            if(ted>d[j]&&txt[j]==0)
            {
                ted=d[j];
                tmp=j;
            }
        }
        if(tmp==n+1) return(0);
        txt[tmp]=1;
        p=a[tmp].next;
        while(p!=&a[tmp])
        {
            if(d[p->to]>d[tmp]+p->dis)
            d[p->to]=d[tmp]+p->dis;
            p=p->next;
        }
    }
    return(0);
}
int front,end;

struct
{
    short node;
    int dis;
}queue[20000001];

int swap(int t,int s)
{
    int tmp=queue[t].node,dis=queue[t].dis;
    queue[t].node=queue[s].node,queue[t].dis=queue[s].dis;
    queue[s].node=tmp,queue[s].dis=dis;
    return(0);
}

int adjust1(int t,int n)
{
    int i=t,j;
    while(i*2<=n)
    {
        j=i*2;
        if(j+1<=n&&queue[j].dis+d[queue[j].node]>queue[j+1].dis+d[queue[j+1].node]) j++;
        if(queue[j].dis+d[queue[j].node]>=queue[i].dis+d[queue[i].node]) break;
        swap(i,j);
        i=j;
    }
    return(0);
}
int adjust2(int n)
{
    int i=n,j;
    while(i/2>=1)
    {
        j=i/2;
        if(queue[i].dis+d[queue[i].node]>=queue[j].dis+d[queue[j].node]) break;
        swap(i,j);
        i=j;
    }
    return(0);
}

int solve(int s,int k)
{
 //   printf("%d\n",time[s]);
    int t=queue[front].node;
    int dis=queue[front].dis;

  //  printf("%d\n",t);

 

    swap(1,end);
    adjust1(1,--end);
//    ++time[t];
    if(++time[t]>k) return(0);
    if(time[s]==k)
    {
        printf("%d\n",dis);
        return(0);
    }

    q=b[t].next;
    while(q!=&b[t])
    {
        queue[++end].node=q->to;
        queue[end].dis=dis+q->dis;
        adjust2(end);
        q=q->next;
    }
}

 


int main()
{
    freopen("in.txt","r",stdin);
    while(scanf("%d %d",&n,&m)!=EOF)
    {
//        printf("hi");
    for(int i=1;i<=n;i++)
    {
        a[i].next=&a[i];
        b[i].next=&b[i];
    }
//    printf("hi");
    for(int i=1;i<=m;i++)
    {
        int from,to,dis;
        scanf("%d %d %d",&to,&from,&dis);
        p=(struct node*)malloc(sizeof(struct node));
        p->next=a[from].next;
        a[from].next=p;
        p->dis=dis;
        p->to=to;

        q=(struct gt*)malloc(sizeof(struct gt));
        q->next=b[to].next;
        b[to].next=q;
        q->dis=dis;
        q->to=from;
    }

    int t,s,k;
    scanf("%d %d %d",&t,&s,&k);
    memset(txt,0,sizeof(txt));
    dijs(s,n);

    front=1;
    end=1;
    queue[front].node=t;
    queue[front].dis=0;

    if(t==s) k++;
    memset(time,0,sizeof(time));
    while(front<=end&&time[s]<k)
    {
//        printf("%d\n",limit[s]);
        solve(s,k);
    }
    if(time[s]<k)
    printf("-1\n");
    }

//    int sum=0;
//   for(int i=1;i<=n;i++)
//    sum+=d[i];
//    printf("%d\n",sum);

//    printf("%d\n",end);
        return 0;
}

你可能感兴趣的:(poj 2449 Remmarguts' Date 第k最…)