poj 2449

poj 2449

给出一个图,求s到t的第k短路


解法:

首先想到搜索,然后发现A*算法的性质是满足的
1> h(i)<=h(j)+cost(i,j)
2> h(i)<=h(i)* [h(i)*表示到达目标状态的实际值]

令估价函数h(i)=h(i)*=dist(i->t)

然后从s开始搜索出第k短路


另外要特判s=t的情况


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXN  1005
#define MAXM  100005
#define SIZE  1000005
#define INF64 200000000

int n,m;
int s,t,k;

struct edge{int v,w,next;}mp[MAXM]={0},mps[MAXM]={0};int ml=0,mls=0;
int head[MAXN]={0};int heads[MAXN]={0};

struct node{int u;long long cost;}heap[SIZE]={0},emp,swap;int hl=0;

int line[MAXN]={0};int f,r;
long long dist[MAXN]={0};

int cnt[MAXN]={0};

char flag[MAXN]={0};

void newedge(int u0,int v0,int w0)
{
    ++ml;
    mp[ml].v=v0;
    mp[ml].w=w0;
    mp[ml].next=head[u0];
    head[u0]=ml;
}
void newedges(int u0,int v0,int w0)
{
    ++mls;
    mps[mls].v=v0;
    mps[mls].w=w0;
    mps[mls].next=heads[u0];
    heads[u0]=mls;
}
void spfa()
{
    int i,c,p;long long tmp;

    for(i=1;i<=n;i++)
      dist[i]=INF64;

    dist[t]=0;
    f=r=0;line[r++]=t;

    while(f!=r)
    {
        c=line[f];f=(f+1)%MAXN;flag[c]=0;

        for(i=heads[c];i;i=mps[i].next)
        {
            p=mps[i].v;

            tmp=dist[c]+mps[i].w;

            if(tmp<dist[p])
            {
                dist[p]=tmp;

              if(!flag[p])
              {
                 flag[p]=1; 

                if(tmp<dist[line[f]])
                {
                    f=(f-1+MAXN)%MAXN;
                    line[f]=p;
                }
                else
                {
                    line[r]=p;
                    r=(r+1)%MAXN;
                }
             }
            }
        }

    }

}

void adjust(int a)
{
    int min=a;
    int l=a<<1,r=l+1;

    if(l<=hl && heap[l].cost<heap[min].cost)min=l;
    if(r<=hl && heap[r].cost<heap[min].cost)min=r;


    if(min!=a)
    {
        swap=heap[a];
        heap[a]=heap[min];
        heap[min]=swap;

        adjust(min);
    }
}


void update(int a)
{
    int fa=a/2;

    if(fa)
    {
        if(heap[fa].cost>heap[a].cost)
        {
           swap=heap[fa];
           heap[fa]=heap[a];
           heap[a]=swap;

           update(fa);
        }
    }
}

long long Astar()
{
    struct node c;
    int p,q,i;


    if(dist[s]==INF64)return -1;



    ++hl;heap[hl].u=s,heap[hl].cost=dist[s];

    while(hl)
    {
        c=heap[1];
       heap[1]=heap[hl];
       heap[hl]=emp;
       hl--;

       if(hl)adjust(1);

       cnt[c.u]++;

       if(c.u==t && cnt[c.u]==k)return c.cost;

       for(i=head[c.u];i;i=mp[i].next)
       {
          p=mp[i].v;

          if(cnt[p]<k)
          {
            ++hl;heap[hl].u=p,heap[hl].cost=c.cost+mp[i].w-dist[c.u]+dist[p];
            update(hl);
          }

       }
    }

    return -1;
}

int main()
{
    int i,a,b,l;

    #ifndef ONLINE_JUDGE 
    freopen("poj2449.in","r",stdin);
    freopen("poj2449.out","w",stdout);
    #endif

    scanf("%d%d",&n,&m); 

    for(i=1;i<=m;i++)
    {
     scanf("%d%d%d",&a,&b,&l);
     newedge(a,b,l);
     newedges(b,a,l);
    }
    scanf("%d%d%d",&s,&t,&k);

    spfa();

    if(s==t)k++;

    printf("%lld",Astar());

    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值