题目链接:http://poj.org/problem?id=2449
大意:
题目意思很简单,就是给你一张图,要求求出从s点到t点的第k短路;
不懂A*算法的可以去看看这篇文章:http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx
值得注意的是:用cin比用scanf多出好几百毫秒
#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=1<<26;
const int MAX=1001;
class Node
{
public:
int v;
int h;
int g;
int f;
friend bool operator < (Node a,Node b)
{
return a.f > b.f;
}
}node;
class ArcNode
{
public:
int to;
int weight;
class ArcNode *next;
};
class ArcNode *list_b[MAX];
int n;
int m;
int dist[MAX];
int ant[MAX];
int graph[MAX][MAX];
bool visit[MAX];
void dijkstra(int x)
{
int i,j;
int min_w;
int pos_flag;
/*Initial*/
memset(visit,false,sizeof(visit));
for(i=1;i<=n;i++)
{
graph[i][i]=0;
dist[i]=graph[x][i];
}
/*Dijkstra Algorithm*/
for(i=1;i<n;i++)
{
min_w=inf;
for(j=1;j<=n;j++)
{
if(!visit[j] && min_w>dist[j])
{
min_w=dist[j];
pos_flag=j;
}
}
visit[pos_flag]=true;
for(j=1;j<=n;j++)
{
if(!visit[j] && dist[j]>dist[pos_flag]+graph[pos_flag][j])
dist[j]=dist[pos_flag]+graph[pos_flag][j];
}
}
return ;
}
int Astar(int sv,int ev,int k)
{
Node vertex;
Node temp_vertex;
ArcNode *temp;
priority_queue <Node> que;
/*Initial*/
vertex.v=sv;
vertex.h=0;
vertex.g=dist[sv];
vertex.f=vertex.h+vertex.g;
que.push(vertex);
/*Astar Algorithm*/
while(!que.empty())
{
vertex=que.top();
que.pop();
ant[vertex.v]++;
if(ant[vertex.v]>k)
continue; //这个点访问次数超过k肯定不在这k条路上
if(ant[vertex.v]==k && vertex.v==ev)
return vertex.h; //第k次到达终点,返回实际走的长度
temp=list_b[vertex.v];
while(temp!=NULL)
{
temp_vertex.v=temp->to; //与之相连的点入队列
temp_vertex.h=vertex.h+temp->weight; //新点的h[x]=h[x']+xx'
temp_vertex.g=dist[temp->to]; //新点的g[x]=dist[x]
temp_vertex.f=temp_vertex.h+temp_vertex.g; //新点的f[x]=h[x]+g[x]
que.push(temp_vertex); //与之相连的点入队列
temp=temp->next;
}
}
return -1;
}
int main()
{
int i,j;
ArcNode *temp;
cin>>n>>m;
/*Initial*/
memset(ant,0,sizeof(ant));
for(i=0;i<MAX;i++)
{
for(j=i;j<MAX;j++)
graph[i][j]=graph[j][i]=inf;
}
/*Structure Graph*/
int u,v,w;
for(i=0;i<m;i++)
{
cin>>u>>v>>w;
temp=(class ArcNode*)malloc(sizeof(class ArcNode)); //正向建边
temp->to=v;
temp->weight=w;
temp->next=NULL;
if(list_b[u]==NULL)
list_b[u]=temp;
else
{
temp->next=list_b[u];
list_b[u]=temp;
}
if(graph[v][u]>w) //反向建边,重边取最小的边
graph[v][u]=w;
}
int s,t,k;
cin>>s>>t>>k;
if(s==t)
k++;
/*Dijkstra求出目标点到各个点的最短距离*/
dijkstra(t);
cout<<Astar(s,t,k)<<endl;
return 0;
}
贴一份别人的代码:
同样是A*+Dijkstra
#include<iostream>
#include<stdlib.h>
#include<queue>
using namespace std;
const int inf=1<<30;
const int M=100010;
const int N=1001;
class Edge //邻接表建边,to是下个结点,w 是权值 nxt 是下条边的位置
{
public:
int to;
int w;
int nxt;
}edge[2*M];
class Data //g 表示起点到当前点的距离,h表终点到当前点的距离
{
public:
int g;
int h;
int to;
bool operator < (Data a) const //优先队列的排序(其实也不能这么讲) 使g+h小的在队首
{
return a.h+a.g<h+g;
}
};
int n;
int edge_num;
int src;
int des;
int head[N]; //正向边
int tail[N]; //逆向边
int dis[N]; //终点到各点的距离
void addedge (int cu,int cv,int cw)
{
edge[edge_num].to=cv;
edge[edge_num].w=cw;
edge[edge_num].nxt=head[cu];
head[cu]=edge_num++;
edge[edge_num].to=cu;
edge[edge_num].w=cw;
edge[edge_num].nxt=tail[cv];
tail[cv]=edge_num++;
}
void dijkstra () //dijkstrastra算法求des到各点的距离 用于估价函数h
{
int i,j;
int pos_flag;
bool visit[N];
/*Initial*/
memset(visit,false,sizeof(visit));
for(i=1;i<=n;i++)
dis[i]=inf;
dis[des]=0;
/*Dijkstra Algorithm*/
for(i=1;i<=n;i++)
{
pos_flag=-1;
int min_dis=inf;
for(j=1;j<=n;j++)
{
if(!visit[j] && min_dis>dis[j])
{
pos_flag=j;
min_dis=dis[j];
}
}
if(pos_flag==-1)
break;
visit[pos_flag]=true;
for(int k=tail[pos_flag];k!=-1;k=edge[k].nxt)
{
int v=edge[k].to;
if(!visit[v] && dis[v]>dis[pos_flag]+edge[k].w)
dis[v]=dis[pos_flag]+edge[k].w;
}
}
return ;
}
int Astar(int k) //A*算法求第k短路
{
int cnt[N];
int i;
Data cur; //当前结点
Data nxt; //下个结点
priority_queue <Data> Ast_que;
/*Initial*/
memset (cnt,0,sizeof(cnt));
cur.to=src;
cur.g=0;
cur.h=dis[src];
Ast_que.push (cur);
/*Astar Algorithm*/
while(!Ast_que.empty())
{
cur=Ast_que.top();
Ast_que.pop();
cnt[cur.to]++;
if(cnt[cur.to]>k)
continue;
if(cnt[des]==k)
return cur.g;
for(i=head[cur.to];i!=-1;i=edge[i].nxt)
{
int v=edge[i].to;
nxt.to=v;
nxt.g=cur.g+edge[i].w;
nxt.h=dis[v];
Ast_que.push(nxt);
}
}
return -1;
}
int main(int m)
{
while(~scanf("%d %d",&n,&m))
{
/*Initial*/
edge_num=0;
memset(head,-1,sizeof (head));
memset(tail,-1,sizeof (tail));
/*Strcture Graph*/
int u,v,w,k;
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
addedge(u,v,w);
}
scanf("%d %d %d",&src,&des,&k);
if(src==des)
k++;
/*Dijkstra求重点到各点的距离*/
dijkstra();
/*Astar Algorithm & Output*/
printf ("%d\n",Astar(k));
}
return 0;
}