• A*


    A*其实就是优化的bfs,让过程更趋近于正确答案,再bfs的基础上多加了个预估函数,依据这个预告函数排序bfs的顺序。

    题:poj2449

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

    题目大意:求出s到t的第k短路大小

    题目思路:如果单用优先队列,那就是从s开始疯狂试探,然后一直到取t第k次的时候就是答案。但是很明显有个缺点,就是他需要走很多无谓的路。

    所以我们需要用到A*算法。A*算法就是多了个估值函数。这里用的是该点到t的最短路值作为估值。

    这样的话,就可以少走很多路,因为知道后来的情况,所以优先队列开头的都是比之前瞎走更加逼近正确答案的点,也就会更快可以将t取出k次。

    这里最短路可以通过建反图获得t到各点的最短路也就变成了各点到t的最短路。有两个注意点,一个是如果s到t的距离是无限大,那么就不用继续直接输出-1,

    还有一个是如果s=t那么需要k++,因为自己到自己距离是0,按照题意不能算第一短的路。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int M=1e5+5;
    const int inf=0x3f3f3f3f;
    int tot,head[M],rhead[M],dis[M],cnt[M],vis[M];
    struct E{
        int v,w,nextt;
    }e[M],re[M];
    void addedge(int u,int v,int w){
        e[tot].v=v;
        e[tot].w=w;
        e[tot].nextt=head[u];
        head[u]=tot;
        re[tot].v=u;
        re[tot].w=w;
        re[tot].nextt=rhead[v];
        rhead[v]=tot++;
    }
    void spfa(int s,int n){
        for(int i=0;i<=n;i++)
            cnt[i]=0,dis[i]=inf,vis[i]=0;
        queue<int>que;
        que.push(s);
        dis[s]=0;
        cnt[s]=1;
        while(!que.empty()){
            int  u=que.front();
            que.pop();
            vis[u]=0;
            for(int i=rhead[u];~i;i=re[i].nextt){
                int v=re[i].v;
                if(dis[v]>dis[u]+re[i].w){
                    dis[v]=dis[u]+re[i].w;
                    if(!vis[v]){
                        que.push(v);
                        vis[v]=1;
                        if(++cnt[v]>n)
                            return ;
                    }
                }
            }
        }
        return ;
    }
    //让dist小的先出队
    struct node{
        /*friend bool operator<(node n1,node n2){
            return n1.dist>n2.dist;
        }*/
        int x,dist;
        bool operator < (const node &b)const{
            return this->dist>b.dist;
        }
    };
    priority_queue<node>q;
    int main(){
        int n,m;
        while(~scanf("%d%d",&n,&m)){
            tot=0;
            for(int i=0;i<=n;i++)
                head[i]=-1,rhead[i]=-1;
            while(m--){
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                addedge(u,v,w);
            }
            int s,t,k;
            scanf("%d%d%d",&s,&t,&k);
            spfa(t,n);
            if(dis[s]==inf){
                puts("-1");
                continue;
            }
            while(!q.empty())
                q.pop();
            node sta;
            sta.x=s,sta.dist=dis[s];
            q.push(sta);
            int ans=-1,num=0;
            if(s==t)
                k++;
            while(!q.empty()){
                node temp=q.top();
                q.pop();
                int u=temp.x;
                if(u==t){
                    num++;
                    if(num==k){
                        ans=temp.dist;
                        break;
                    }
                }
                for(int i=head[u];~i;i=e[i].nextt){
                    int v=e[i].v;
                    node close;
                    close.x=v;
                    close.dist=temp.dist-dis[u]+dis[v]+e[i].w;
                    q.push(close);
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    oracle minus 与sqlserver except
    Ext.form.FieldSetI(转)
    C#系统服务定时执行(转)
    extjs4.0的数据代理proxy及数据模型的使用(转)
    JS属性defer的好处及IE8 提示 KB927917, IE6 IE7 提示操作已中止的解决办法
    水晶报表打印及多个报表打印到一个PDF文件里的办法
    C#不添加引用,动态调用webservice(转)
    向 ReportViewer 报表中添加页眉和页脚,控制页眉显示变量的值
    网站主要使用jquery总结(转)
    JSBuilder2使用方法(转)
  • 原文地址:https://www.cnblogs.com/starve/p/10999145.html
Copyright © 2020-2023  润新知