zoukankan      html  css  js  c++  java
  • [bzoj1598][Usaco08Mar]牛跑步_A*_Dijkstra

    牛跑步 bzoj-1598

    题目大意:给你n个点,m条边的有向图。求从1到n的严格的第k短路。

    注释:$1le nle 1000$,$1le m le 10,000$,$1le k le 100$。

    想法

      A*:俗称机器人走路算法。就是说从一个点走到另一个点的最短路径,显然可以bfs。我们可以在bfs时设立估价函数来判断queue中先取出那个点。

      比如说这道题,我们先将所有边存起来,先都连反向边。然后从n节点开始跑一遍堆优化dij表示这个点到n的最短路。然后我们从1号节点开始bfs。我们将所有遍历到的节点扔进堆,堆中的估价函数是从源点到当前状态的长度dis加上从当前节点到n的最短路。这样的话,第一个到的点一定是最短路,第二个同理,以此类推,知道我们在n节点已经接收到了k个不同的值,break输出答案即可。

    最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <stdlib.h>
    #define N 100010 
    using namespace std;
    int ans[N];
    int tot,head[N],to[N],nxt[N],val[N];
    int H[N];
    struct Node
    {
    	int dis,id;
    	Node(){}
    	Node(int dis_,int id_):dis(dis_),id(id_){}
    	inline bool operator < (const Node &x) const
    	{
    		return dis+H[id]>x.dis+H[x.id];
    	}
    };
    priority_queue<Node> q;
    priority_queue<pair<int,int> >Q;
    bool v[N];
    inline void add(int x,int y,int z)
    {
    	to[++tot]=y;
    	val[tot]=z;
    	nxt[tot]=head[x];
    	head[x]=tot;
    }
    int x[N],y[N],z[N];
    int n;
    bool vis[N];
    void Dij()
    {
    	memset(H,0x3f,sizeof H);
    	memset(vis,0,sizeof vis);
    	H[n]=0;
    	Q.push(make_pair(0,n));
    	while(!Q.empty())
    	{
    		int a=Q.top().second;
    		Q.pop();
    		if(vis[a]) continue;
    		vis[a]=1;
    		for(int i=head[a];i;i=nxt[i])
    		{
    			if(H[to[i]]>H[a]+val[i])
    			{
    				H[to[i]]=H[a]+val[i];
    				Q.push(make_pair(-H[to[i]],to[i]));
    			}
    		}
    	}
    }
    int cnt=0;
    void A_xing(int num)
    {
    	q.push(Node(0,1));
    	while(!q.empty())
    	{
    		Node t=q.top();
    		q.pop();
    		int a=t.id;
    		int distance=t.dis;
    		if(a==n)
    		{
    			ans[++cnt]=distance;
    			// puts("Fuck");
    		}
    		if(cnt==num) return;
    		for(int i=head[a];i;i=nxt[i])
    		{
    			int w=distance+val[i];
    			/*if(!mp.count(make_pair(w,to[i])))
    			{
    				mp[make_pair(w,to[i])]=1;
    				q2.push(node(w,to[i]));
    			}*/
    			q.push(Node(w,to[i]));
    		}
    	}
    }
    int main()
    {
    	int r,k;
    	scanf("%d%d%d",&n,&r,&k);
    	for(int i=1;i<=r;i++)
    	{
    		scanf("%d%d%d",&x[i],&y[i],&z[i]);
    		add(x[i],y[i],z[i]);
    	}
    	Dij();
    	memset(head,0,sizeof head);
    	tot=0;
    	for(int i=1;i<=r;i++)
    	{
    		add(y[i],x[i],z[i]);
    	}
    	// for(int i=1;i<=n;i++)
    	// {
    	// 	printf("%d:%d
    ",i,H[i]);
    	// }
    	A_xing(k);
    	for(int i=1;i<=k;i++)
    	{
    		if(i<=cnt) printf("%d
    ",ans[i]);
    		else printf("-1
    ");
    	}
    	return 0;
    }

    小结:这种毒瘤算法好像少接触为妙。

  • 相关阅读:
    [大数据从入门到放弃系列教程]在IDEA的Java项目里,配置并加入Scala,写出并运行scala的hello world
    [大数据从入门到放弃系列教程]第一个spark分析程序
    Mac配置Scala和Spark最详细过程
    Mac配置Hadoop最详细过程
    [从零开始搭网站八]CentOS使用yum安装Redis的方法
    CentOS磁盘用完的解决办法,以及Tomcat的server.xml里无引用,但是项目仍启动的问题
    Mysql 删除重复数据只保留id最小的
    bootstrap媒体查询常用写法
    Arduino Uno 在win7 64位下的驱动问题
    VS项目模板文件位置
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9084996.html
Copyright © 2011-2022 走看看