• [POJ2449] Remmarguts' Date


    Description

    "Good man never makes girls wait or breaks an appointment!" said the mandarin duck father. Softly touching his little ducks' head, he told them a story.

    "Prince Remmarguts lives in his kingdom UDF – United Delta of Freedom. One day their neighboring country sent them Princess Uyuw on a diplomatic mission."

    "Erenow, the princess sent Remmarguts a letter, informing him that she would come to the hall and hold commercial talks with UDF if and only if the prince go and meet her via the K-th shortest path. (in fact, Uyuw does not want to come at all)"

    Being interested in the trade development and such a lovely girl, Prince Remmarguts really became enamored. He needs you - the prime minister's help!

    DETAILS: UDF's capital consists of N stations. The hall is numbered S, while the station numbered T denotes prince' current place. M muddy directed sideways connect some of the stations. Remmarguts' path to welcome the princess might include the same station twice or more than twice, even it is the station with number S or T. Different paths with same length will be considered disparate.

    Input

    The first line contains two integer numbers N and M (1 <= N <= 1000, 0 <= M <= 100000). Stations are numbered from 1 to N. Each of the following M lines contains three integer numbers A, B and T (1 <= A, B <= N, 1 <= T <= 100). It shows that there is a directed sideway from A-th station to B-th station with time T.

    The last line consists of three integer numbers S, T and K (1 <= S, T <= N, 1 <= K <= 1000).

    Output

    A single line consisting of a single integer number: the length (time required) to welcome Princess Uyuw using the K-th shortest path. If K-th shortest path does not exist, you should output "-1" (without quotes) instead.

    Sample Input

    2 2
    1 2 5
    2 1 4
    1 2 2
    

    Sample Output

    14
    

    Source

    POJ Monthly,Zeyuan Zhu

    题意

    (n)个点(m)条边的有向图,求图中两点间第(K)短路。

    • 输入第一行为顶点数(N),边数(M)

    • 接下来(2)(M+1)行,每行(3)个数:(u)(v)(w),表示(u)(v)有一条边权为(w)的有向边;

    • 最后一行(3)个整数:(From)(To)(Cnt),表示题目要求求(From)(To)的第(Cnt)小的路径。

    • (PS):如果没有(From)(To)的第(Cnt)小的路径,则输出(-1)

    题解

    (K)短路的模板题,这里着重讲解一下思路:

    首先我们需要用两个边集数组,一个用来记录输入的边的信息,另一个记录反向边。

    再以终点为源点跑一趟(Dijkstra),注意边要用反向边。

    接下来才是重点:(A*)求第(K)短路,我们先解释定义

    struct node
    {
    	int id,f,g;
    	bool operator<(node tmp) const
    	{
    		if(f==tmp.f) return g>tmp.g;
    		return f>tmp.f;
    	}
    };
    priority_queue<node> q;
    
    • (id)记录当前的点的编号

    • (f)为一个估计:按照当前到达(id)(+)(id)到达(To)的最段路,即按照当前的遍历了的总边权与后面估计距离的最小值

    • (g)为已经遍历了的总边权

    再看看(A*)算法的核心:

    void A_star()
    {
    	if(From==To) ++Cnt;
    	q.push((node){From,0,0});
    	node nw; int to;
    	while(!q.empty())
    	{
    		nw=q.top(); q.pop();
    		if(nw.id==To)
    			if(!(--Cnt)) {printf("%d
    ",nw.g);return;}
    		for(int i=hd1[nw.id];i;i=e1[i].nt)
    		{
    			to=e1[i].to;
    			q.push((node){to,nw.g+e1[i].ds+dis[to],nw.g+e1[i].ds});
    		}
    	}
    	puts("-1");
    }
    
    • 首先的这个是个坑点:if(From==To) ++Cnt;,即起点等于终点的情况

    • 接下来的(BFS)难度不大,此处不予以解释

    上代码:

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #include<string>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<set>
    #include<map>
    #include<bitset>
    using namespace std;
    
    const int N=5001,NE=200001;
    struct edge
    {
    	int to,ds,nt;
    }e1[NE],e2[NE];
    int n,m,ne1,ne2,hd1[N],hd2[N],dis[N],From,To,Cnt;
    
    void Read()
    {
    	int u,v,w;
    	for(scanf("%d%d",&n,&m);m;--m)
    	{
    		scanf("%d%d%d",&u,&v,&w);
    		++ne1,e1[ne1]=(edge){v,w,hd1[u]},hd1[u]=ne1,
    		++ne2,e2[ne2]=(edge){u,w,hd2[v]},hd2[v]=ne2;
    	}
    	scanf("%d%d%d",&From,&To,&Cnt);
    }
    
    typedef pair<int,int> pr;
    priority_queue<pr,vector<pr>,greater<pr> > Q;
    bool vis[N];
    const int INF=99999999;
    void Dijkstra(int s)
    {
    	for(int i=1;i<=n;++i) dis[i]=INF;
    	dis[s]=0;
    	Q.push(make_pair(dis[s],s));
    	int nw,nt;
    	while(!Q.empty())
    	{
    		nw=Q.top().second; Q.pop();
    		if(vis[nw]) continue;
    		vis[nw]=1;
    		for(int i=hd2[nw];i;i=e2[i].nt)
    		{
    			nt=e2[i].to;
    			if(dis[nt]>dis[nw]+e2[i].ds)
    			{
    				dis[nt]=dis[nw]+e2[i].ds;
    				Q.push(make_pair(dis[nt],nt));
    			}
    		}
    	}
    }
    
    struct node
    {
    	int id,f,g;
    	bool operator<(node tmp) const
    	{
    		if(f==tmp.f) return g>tmp.g;
    		return f>tmp.f;
    	}
    };
    priority_queue<node> q;
    
    void A_star()
    {
    	if(From==To) ++Cnt;
    	q.push((node){From,0,0});
    	node nw; int to;
    	while(!q.empty())
    	{
    		nw=q.top(); q.pop();
    		if(nw.id==To)
    			if(!(--Cnt)) {printf("%d
    ",nw.g);return;}
    		for(int i=hd1[nw.id];i;i=e1[i].nt)
    		{
    			to=e1[i].to;
    			q.push((node){to,nw.g+e1[i].ds+dis[to],nw.g+e1[i].ds});
    		}
    	}
    	puts("-1");
    }
    
    int main()
    {
    	Read(),
    	Dijkstra(To),
    	A_star();
    	return 0;
    }
    

    本文作者:OItby @ https://www.cnblogs.com/hihocoder/

    未经允许,请勿转载。

  • 相关阅读:
    支付宝API
    三级联动
    高精尖面试题(七)
    高精尖面试题(六)
    高精尖面试题(五)
    第十二章、使用继承
    第十章、使用数组
    第十一章、理解参数数组
    第九章、使用枚举和结构创建值类型
    第八章、理解值类型和引用
  • 原文地址:https://www.cnblogs.com/hihocoder/p/11479293.html
Copyright © 2020-2023  润新知