次短路,第k最短路,有限制的最短路问题总结

在这求第k短路用的是,A*+dij所谓的A*是一种启发式搜索,他给搜索选定一定的方向,避免了无谓的搜索,如何来确定搜索的顺序?也就是用一个值来表示这个值为f[x],每次搜索取f[x]最小的拓展,那么这个f[x]=h[x]+g[x]其中这个h[x]就是当前搜索时的代价,如求K段路这个就是前一个点的h[x']+边的长度,而g[x]是一个估价函数,估价函数要小于是对当前点到目标的代价的估计,这个估计必须小于等于实际值,否则会出错。A*的关键也就是构造g[x],我们的dij算法。最短路就是一种A*搜索,其中g[x]=0。

而这里要说的求K短路一种方法,就是用BFS+A*来搜索的过程,g[x]的设定为到这个点到目标点的最短路(这个可以用dij一次求出)径,显然其实小于等于实际值的,h[x]就是搜索到这个点的代价(及走过的路程),用一个优先队列来做,每次取出h[x]+g[x]最小的点来拓展。拓展,也就是通过这点来更新其能直接经过一条边到达的点,这里做好一个新点就丢进优先队列里去,反正总会从对首弹出h[x]+g[x]最小的点。

首先,我们在放优先队列的是这样的节点,他包括,从原点到达本节点的路径长度len,然后我们在优先列里,按照len+dis[i](dis到达终点的最短路)的最小,优先级排队,那么当我们第一次搜索到E点时,这时肯定是最短路径,第二次取出的,就是第二短路,以此类推,从而可以求出第k短路。

struct cnode
{
    int u;
    int len;
    cnode (int uu,int ww):u(uu),len(ww){}
    friend bool operator < (cnode a,cnode b)
    {
        return a.len+dis[a.u]>b.len+dis[b.u];
    }
};

我们从一个点,如何扩展下一个点呢,就是将与相连的点,入队列(这样就会走重复的边),队列里面的节点就是,原点经过len的路经所到达的状态

int A_star(int s)
{
    int i;
    if(dis[s]==inf)return -1;//这个一定要有,若s到t不连通的话,下面会 死循环
    priority_queueque;
    CL(tol,0);
    que.push(cnode(s,0));
    while(!que.empty())
    {
        cnode a=que.top();que.pop();
        int u=a.u;
        int len=a.len;
        tol[u]++;
        if(tol[t]==k)return len;
        for(i=0;i

那要是本身就不存在K短路呢?那就是e拓展不到K但是其他点很有可能一直打圈圈无限下去,这里就要用个条件来判断一 下。首先在找某个点作为优先队列头出现了几次就用了一个计数器times[],所求的点times[e]==k就代表得到了解,如果当前想拓展的点times[]>k就没必要拓展了,因为这个点已经是求到k+1短路了,从这个点继续往下搜肯定得到的是大于等于k+1短路的路径,就像1->2有3条路,2->3有2条路,那1->3有6条路的概念差不多,没必要对其进行拓展了。

注意 :若是有向边时,我们求到终点的最短距离时,要将边反向。

poj 2449   Remmarguts' Date   (有向边)

http://poj.org/problem?id=2449

求任意两点的第k短路

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define CL(a,num)  memset(a,num,sizeof(a));
#define inf 9999999
#define maxn 1030
#define eps  1e-6
struct node
{
    int u;
    int w;
    node (int uu,int ww):u(uu),w(ww){}
};
vectorg[maxn],rg[maxn];
int dis[maxn],vis[maxn],tol[maxn];
struct cnode
{
    int u;
    int len;
    cnode (int uu,int ww):u(uu),len(ww){}
    friend bool operator < (cnode a,cnode b)
    {
        return a.len+dis[a.u]>b.len+dis[b.u];
    }
};
int n,m,s,t,k;
void spfa(int s)
{
    int i;
    for(i=0;i<=n;i++)
    {
        dis[i]=inf;
        vis[i]=0;
    }
    dis[s]=0;
    queueque;
    que.push(s);
    while(!que.empty())
    {
        int u=que.front();que.pop();
        vis[u]=0;
        for(i=0;idis[u]+b.w)
            {
                dis[v]=dis[u]+b.w;
                if(!vis[v])
                {
                    vis[v]=1;
                    que.push(v);
                }
            }
        }
    }
}
int A_star(int s)
{
    int i;
    if(dis[s]==inf)return -1;
    priority_queueque;
    CL(tol,0);
    que.push(cnode(s,0));
    while(!que.empty())
    {
        cnode a=que.top();que.pop();
        int u=a.u;
        int len=a.len;
        tol[u]++;
        if(tol[t]==k)return len;

        for(i=0;i

poj 3255  Roadblocks

求1到n的次短路

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CL(a,num)  memset(a,num,sizeof(a));
#define inf 9999999
#define maxn 5030
#define eps  1e-6
using namespace std;
int n,k,m;
int dis[maxn],tol[maxn],vis[maxn];
struct node
{
    int u;
    int w;
    node (int uu,int ww):u(uu),w(ww){}
};
vectorg[maxn];
struct anode
{
    int  u;
    int len;
    anode(int uu,int w):u(uu),len(w){}
    friend bool operator < (anode a, anode b)
    {
        return a.len+dis[a.u]>b.len+dis[b.u];
    }
};
void SPFA(int x)
{
    int i;
    for(i=0;i<=n;i++)
    {
        dis[i]=inf;
        vis[i]=0;
    }
    dis[n]=0;
    queueque;
    que.push(n);
    vis[n]=1;
    while(!que.empty())
    {
        int u=que.front();que.pop();
        vis[u]=0;
        for(i=0;idis[u]+b.w)
            {
                dis[v]=dis[u]+b.w;
                if(!vis[v])
                {
                    vis[v]=1;
                    que.push(v);
                }
            }
        }
    }
}
int  A_star(int s)
{
    int i;
    if(dis[s]==inf)return -1;
    priority_queueque;
    CL(tol,0);
    que.push(anode(1,0));
    while(!que.empty())
    {
        anode a=que.top();que.pop();
        int u=a.u;
        int len=a.len;
        tol[u]++;
        if(tol[n]==k)return len;
        for(i=0;i

poj 3767 I Wanna Go Home (有限制的最短路)

http://poj.org/problem?id=3767
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CL(a,num)  memset(a,num,sizeof(a));
#define inf 9999999
#define maxn 1030
#define eps  1e-6
using namespace std;
int n,m;
int mat[maxn][maxn],vis[maxn],pre[maxn],f[maxn],dis[maxn];
void init()
{
    for(int i=0;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
            mat[i][j]=inf;
    }
}
void dij()
{
    int i,j,k;
    for(i=0;i<=n;i++)
    {
        dis[i]=inf;
        vis[i]=0;
        pre[i]=0;
    }
    dis[1]=0;
    pre[1]=1;
    for(i=0;idis[k]+mat[k][j])
                dis[j]=dis[k]+mat[k][j];
        }
    }
}
int main()
{
    int i,x,y,z,a,j;
    while(scanf("%d",&n),n)
    {
        scanf("%d",&m);
        init();
        for(i=1;i<=m;i++)
        {
            scanf("%d %d %d",&x,&y,&z);
            mat[x][y]=mat[y][x]=z;
        }
        for(i=1;i<=n;i++)
        {
          scanf("%d",&f[i]);

        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                if(f[i]!=f[j])
                {
                    if(f[i]==1&&f[j]==2)
                        mat[j][i]=inf;
                    else
                       if(f[j]==1&&f[i]==2)
                        mat[i][j]=inf;
                }
            }
        }
        dij();
        if(dis[2]!=inf)
            printf("%d\n",dis[2]);
        else 
            printf("-1\n");
    }
    return 0;
}


你可能感兴趣的:(图论)