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

来源:互联网 发布:小米 禁止安装软件 编辑:程序博客网 时间:2024/05/18 01:12

在这求第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_queue<cnode>que;    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<g[u].size();i++)        {            node b=g[u][i];            int v=b.u;            que.push(cnode(v,len+b.w));        }    }    return -1;}

那要是本身就不存在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<functional>#include<algorithm>#include<iostream>#include<fstream>#include<sstream>#include<iomanip>#include<numeric>#include<cstring>#include<climits>#include<cassert>#include<cstdio>#include<string>#include<vector>#include<bitset>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<list>#include<set>#include<map>using namespace std;#define CL(a,num)  memset(a,num,sizeof(a));#define inf 9999999#define maxn 1030#define eps  1e-6struct node{    int u;    int w;    node (int uu,int ww):u(uu),w(ww){}};vector<node>g[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;    queue<int>que;    que.push(s);    while(!que.empty())    {        int u=que.front();que.pop();        vis[u]=0;        for(i=0;i<rg[u].size();i++)        {            node b=rg[u][i];            int v=b.u;            if(dis[v]>dis[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_queue<cnode>que;    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<g[u].size();i++)        {            node b=g[u][i];            int v=b.u;            que.push(cnode(v,len+b.w));        }    }    return -1;}int main(){    int i,x,y,z;    while(scanf("%d %d",&n,&m)!=EOF)    {        for(i=0;i<=n;i++)g[i].clear();        for(i=0;i<m;i++)        {            scanf("%d %d %d",&x,&y,&z);            g[x].push_back(node(y,z));            rg[y].push_back(node(x,z));        }        scanf("%d %d %d",&s,&t,&k);        if(s==t)k++;        spfa(t);        int ans=A_star(s);        printf("%d\n",ans);    }    return 0;}

poj 3255  Roadblocks

求1到n的次短路

#include<functional>#include<algorithm>#include<iostream>#include<fstream>#include<sstream>#include<iomanip>#include<numeric>#include<cstring>#include<climits>#include<cassert>#include<cstdio>#include<string>#include<vector>#include<bitset>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<list>#include<set>#include<map>#define CL(a,num)  memset(a,num,sizeof(a));#define inf 9999999#define maxn 5030#define eps  1e-6using 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){}};vector<node>g[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;    queue<int>que;    que.push(n);    vis[n]=1;    while(!que.empty())    {        int u=que.front();que.pop();        vis[u]=0;        for(i=0;i<g[u].size();i++)        {            node b=g[u][i];            int v=b.u;            if(dis[v]>dis[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_queue<anode>que;    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<g[u].size();i++)        {            node b=g[u][i];            int v=b.u;            que.push(anode(v,len+b.w));        }    }    return -1;}int main(){    int i,x,y,z;    scanf("%d %d",&n,&m);            k=2;        for(i=0;i<m;i++)        {            scanf("%d %d %d",&x,&y,&z);            g[x].push_back(node(y,z));            g[y].push_back(node(x,z));        }        SPFA(n);        int ans=A_star(1);        printf("%d\n",ans);        return 0;}

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

http://poj.org/problem?id=3767
#include<functional>#include<algorithm>#include<iostream>#include<fstream>#include<sstream>#include<iomanip>#include<numeric>#include<cstring>#include<climits>#include<cassert>#include<cstdio>#include<string>#include<vector>#include<bitset>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<list>#include<set>#include<map>#define CL(a,num)  memset(a,num,sizeof(a));#define inf 9999999#define maxn 1030#define eps  1e-6using 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;i<n;i++)    {        int min=inf;        for(j=1;j<=n;j++)        {            if(!vis[j]&&dis[j]<min)            {                min=dis[j];                k=j;            }        }        vis[k]=1;        for(j=1;j<=n;j++)        {            if(!vis[j]&mat[k][j]!=inf&&dis[j]>dis[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;}