zoukankan      html  css  js  c++  java
  • A* k短路 学习笔记

    题目大意

    n个点,m条边有向图,给定S,T,求不严格k短路
    n<=1000 m<=100000 k<=1000
    不用LL

    分析

    A*算法
    f(i)表示从S出发经过i到T的估价函数
    (f(i)=g(i)+h(i))
    g(i)表示S-i的实际代价
    h(i)表示i-T的估计代价
    要保证h(n)小于等于n到t的实际代价
    本题中h(i)估价用逆图dijkstra一波直接求i-T最短路径作为估价
    然后从S开始按照f为关键字用堆优化搜索
    其实写法是类似于dijkstra的
    不难从f(i)如果出现了K+1短,K+1短及之后都可以不要的
    所以记录cnt[i]
    每个点i出队一次,就找到了第++cnt[i]个f(i)
    当T第k次出队就是答案

    注意

    dijkstra和Astar是可以共用一个结构体进行堆优化的

    solution

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int N=1007;
    const int M=100007;
    
    inline int rd(){
    	int x=0;bool f=1;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
    	for(;isdigit(c);c=getchar()) x=x*10+c-48;
    	return f?x:-x;
    }
    
    int n,m;
    int S,K,T;
    int g[N],te;
    int hd[N],tb;
    struct edge{
    	int y,d,next;
    }e[M<<1],bck[M<<1];
    
    void addedge(int x,int y,int z){
    	e[++te].y=y;e[te].d=z;e[te].next=g[x];g[x]=te;
    }
    
    void addbck(int x,int y,int z){
    	bck[++tb].y=y;bck[tb].d=z;bck[tb].next=hd[x];hd[x]=tb;
    }
    
    struct node{
    	int id,g,f;
    	node(int ii=0,int gg=0,int ff=0){id=ii;g=gg;f=ff;}
    	bool operator < (node b) const{
    		return f>b.f;
    	}
    };
    
    priority_queue<node>q;
    
    int h[N],vis[N];
    
    void dijkstra(){
    	q.push(node(T,0,0));
    	memset(h,127,sizeof(h));
    	h[T]=0;
    	
    	int x,p,y;
    	node nw;
    	while(!q.empty()){
    		nw=q.top();q.pop();
    		x=nw.id;
    		if(vis[x]) continue;
    		vis[x]=1;
    		for(p=hd[x];p;p=bck[p].next){
    			y=bck[p].y;
    			if(h[x]+bck[p].d<h[y]){
    				h[y]=h[x]+bck[p].d;
    				q.push(node(y,0,h[y]));
    			}
    		}
    	}
    }
    
    int cnt[N];
    
    bool Astar(){
    	q.push(node(S,0,h[S]));
    	int x,p,y;
    	node nw;
    	while(!q.empty()){
    		nw=q.top();q.pop();
    		x=nw.id;
    		cnt[x]++;
    		if(cnt[x]==K&&x==T){
    			printf("%d
    ",nw.f);
    			return 1;
    		}
    		if(cnt[x]>K) continue;
    		for(p=g[x];p;p=e[p].next){
    			y=e[p].y;
    			q.push(node(y,nw.g+e[p].d,nw.g+e[p].d+h[y]));
    		}
    	}
    	return 0;
    }
    
    int main(){
    	int i,x,y,z;
    	n=rd(),m=rd();
    	for(i=1;i<=m;i++){
    		x=rd(),y=rd(),z=rd();
    		addedge(x,y,z);
    		addbck(y,x,z);
    	}
    	S=rd(),T=rd(),K=rd();
    	dijkstra();
    	if(Astar()==0) puts("-1");
    	return 0;
    }
    
  • 相关阅读:
    python 运行CMD和shell命令
    python 装饰器2 常用装饰器【@property,@x.setter,@x.deleter】
    正则表达式 python re正则模块
    Interesting Finds: 2008.01.06
    Interesting Finds: 2008.01.11
    Interesting Finds: 2007.12.25
    Interesting Finds: 2007.12.26
    Interesting Finds: 2008.01.04
    Interesting Finds: 2008.01.03
    Interesting Finds: 2008.01.09
  • 原文地址:https://www.cnblogs.com/acha/p/6399004.html
Copyright © 2011-2022 走看看