pku2449第K短路 最短路+A*

        题意:求一点至另一点的第K短路。注意如果起点和终点一样的话,那么刚开始起点不算到达终点。

        分析:寻找最短路,直接SPFA就可以了。。。这里是第K短路,把每一条路径都找出来。开始想用DP,dp[i][j]表示到i结点第j大的路径权值是多少,但这样还是搜,而且会超时。。。所以还不如用A*搜,用优先队列每次将按照所走路径权值的最小值+此点到终点的最短距离的最小值出队列。

        注意计算第几次到达某个点时是以出队列的时候算的,而不是入队列。开始求每个点到终点的最短路,建反向图,再用SPFA。。。

#include
#include
#include
#include
using namespace std;

const int maxn=1100;
const int maxm=110000;
const int INF=0x3fffffff;
struct edge
{
	int u,v,w;
}p0,p1;

vectore[maxn],e1[maxn];

int dist[maxn],times[maxn],n,m,S,T,K;

bool operator >(edge a,edge b)
{
	return a.w+dist[a.v]>b.w+dist[b.v];
}
priority_queue,greater >p;

void SPFA(int s)
{
	int i,j,k,head=0,tail=0,q[maxn*2];
	bool inq[maxn];
	for(i=1;i<=n;i++)
		dist[i]=INF,inq[i]=false;
	dist[s]=0,inq[s]=true;
	q[tail++]=s;
	while(head!=tail)
	{
		k=q[head];
		inq[k]=false;
		head=(head+1)%(2*maxn);
		for(i=0;idist[k]+e1[k][i].w)
			{
				dist[j]=dist[k]+e1[k][i].w;
				if(!inq[j])
				{
					inq[j]=true;
					q[tail]=j;
					tail=(tail+1)%(2*maxn);
				}
			}
		}
	}
}
void Search()
{
	int i,now;
	bool tag=false;
	while(!p.empty()) p.pop();
	memset(times,0,sizeof(times));
	p0.v=S,p0.w=0;
	p.push(p0);
	while(!p.empty())
	{
		p0=p.top();
		p.pop();
		if(++times[p0.v]>=K)
		{
			if(p0.v==T)
			{
				if(S!=T||(S==T&×[p0.v]==K+1))//如果起点和终点一样,那么一定要走才算一条路径
				{
					tag=true;
					printf("%d\n",p0.w);
					break;
				}
			}
			if(times[p0.v]>K)
				continue;
		}
		now=p0.v;
		for(i=0;i


 

你可能感兴趣的:(搜索,图论,search,ie)