zoukankan      html  css  js  c++  java
  • poj 2449 Remmarguts' Date 夜

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

    第k短路 刚开始上网找了分标准解法 没看懂呀 汗   然后看别人都用了A*算法  我也不知道是

    什么东西

    如果我们用队列枚举的话 当第k次出现终点 则这时就是到终点的第k短路 

    但是这样队列是承受不住的 因为数据会太多

    对于这道题 思路好像基本上就是

    构造一个函数 f(i)=g(i)+h(i)    g为出发点到i的最短距离 h为终点到i的最短距离

    f 为他们的和但每次取f最小的点进行更新

    直到终点出现第k次 既为答案

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<string.h>
    
    using namespace std;
    
    const int N=1001;
    const int M=1000005;
    const int MAX=0x5fffffff;
    struct ss
    {
        int x,y;
        int d;
    }mem[M];
    int head[N];
    struct to
    {
        int j,k;
        int next;
    }side[M];
    struct node
    {
        int f,g;
        int x;
        bool operator <(const node a) const
        {
            if(a.f==f)
            return a.g<g;
            return a.f<f;
        }
    };
    priority_queue< node >str;
    void build(int x,int i)
    {
        side[i].next=head[x];
        head[x]=i;
    }
    int dist[N];
    int had[N];
    void spfa(int s,int n)
    {
        queue<int>st;
        memset(had,0,sizeof(had));
        for(int i=1;i<=n;++i)
        dist[i]=MAX;
        dist[s]=0;
        had[s]=1;
        st.push(s);
        while(!st.empty())//求到终点最短距离
        {
            int x=st.front();
            st.pop();
            had[x]=0;
            int t=head[x];
            while(t!=-1)
            {
                if(dist[side[t].j]>dist[x]+side[t].k)
                {
                    dist[side[t].j]=dist[x]+side[t].k;
                    if(!had[side[t].j])
                    {
                        st.push(side[t].j);
                        had[side[t].j]=1;
                    }
                }
                t=side[t].next;
            }
        }
    }
    int Astar(int S,int T,int k,int n)
    {
        if(dist[S]==MAX)
        return -1;
        if(S==T)//这里坑嗲
        ++k;
        while(!str.empty())
        str.pop();
        node k1,k2;
        k1.f=dist[S];
        k1.x=S;
        k1.g=0;
        str.push(k1);//用优先队列实现 
        memset(had,0,sizeof(had));
        while(!str.empty())
        {
            k1=str.top();//每次取f最小
            str.pop();
            ++had[k1.x];
            if(had[T]==k)//不断寻找 直到终点第 k 次出现 就是第k短路
            return k1.g;
            if(had[k1.x]>k)
            continue;
            int t=head[k1.x];
            while(t!=-1)
            {
                k2.x=side[t].j;
                if(dist[k2.x]==MAX)
                {
                    t=side[t].next;continue;
                }
                k2.g=k1.g+side[t].k;
                k2.f=k2.g+dist[k2.x];
                str.push(k2);
                t=side[t].next;
            }
        }
        return -1;
    }
    int main()
    {
        freopen("data.txt","r",stdin);
        int n,m,k,S,T;
        while(scanf("%d %d",&n,&m)!=EOF)
        {
            memset(head,-1,sizeof(head));
            for(int i=0;i<m;++i)
            {
                scanf("%d %d %d",&mem[i].x,&mem[i].y,&mem[i].d);
                side[i].j=mem[i].x;
                side[i].k=mem[i].d;//建反向图
                build(mem[i].y,i);
            }
            scanf("%d %d %d",&S,&T,&k);
            spfa(T,n);//求到终点 最短路
            memset(head,-1,sizeof(head));
            for(int i=0;i<m;++i)
            {
                side[i].j=mem[i].y;
                build(mem[i].x,i);//建正向边
            }
            printf("%d\n",Astar(S,T,k,n));//A×
        }
        return 0;
    }
    

      

  • 相关阅读:
    struts2 + ajax(从后台获取json格式的数据返回到前端,然后前端用jquery对json数据进行解析)
    request 中文乱码问题
    Eclipse 支持jQuery 自动提示
    基于按annotation的hibernate主键生成策略
    微信创建菜单操作
    百度转换经纬度为地址
    微信工具类(常用接口)的整理
    微信URL有效性验证
    原型模式 (原型管理器)
    发送邮件 Email(java实现)
  • 原文地址:https://www.cnblogs.com/liulangye/p/2626132.html
Copyright © 2011-2022 走看看