hdu 2066 一个人的旅行 dijkstra入门题


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2066


复习下最朴素的dijkstra算法:


主要是扩展每个节点,如果有n个点,主循环为n次。


然后每次选择一个没有扩展并且最优的点(最短距离最短)进行拓展。


拓展方式根据选择邻接表或邻接矩阵有所差异,当然是邻接表比较快啦!。



#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s)  memset(a,x,(s)*sizeof a[0])
#define mem(a,x)  memset(a,x,sizeof a)
#define ysk(x)  (1<<(x))
typedef long long ll;
const int INF = 0x3f3f3f3f ;
const int maxn= 1000 ;

struct Edge
{
	int to,w,nex;
	Edge(){}
	Edge(int to,int w,int nex):to(to),w(w),nex(nex){}
}e[2*maxn+10];
int nedge,fir[maxn+3];

int n,m,num,nwant;


void add_edge(int x,int y,int w)
{
	e[nedge]=Edge(y,w,fir[x]);
	fir[x]=nedge++;

}


int dp[maxn+3];
bool done[maxn+3];

void dijkstra()
{
	mem(dp,0x3f);dp[0]=0;
	mem(done,0);
	
	for0(i,n+1)
	{
		int mini=INF,k;
		for0(j,n+1) if(!done[j]&&dp[j]<mini)
		{
			mini=dp[j];
			k=j;
		}

		done[k]=1;

		for(int ed=fir[k];~ed;ed=e[ed].nex)
		{
			int to=e[ed].to,w=e[ed].w;	
			if(done[to]) continue;

			if(dp[k]+w<dp[to])
			{
				dp[to]=dp[k]+w;
			}		
		}

	}


}
int main()
{
	int x,y,w;
	while(~scanf("%d%d%d",&m,&num,&nwant))
	{
		nedge=n=0;mem(fir,-1);

		for0(i,m)
		{
			scanf("%d%d%d",&x,&y,&w);
			add_edge(x,y,w);
			add_edge(y,x,w);
			n=max(n,x);
			n=max(n,y);
		}

		for0(i,num)
		{
			scanf("%d",&x);
			add_edge(0,x,0);
			add_edge(x,0,0);
		}

		dijkstra();

		int ans=INF;
		for0(i,nwant)
		{
			scanf("%d",&x);
			ans=min(ans,dp[x]);
		}
		printf("%d\n",ans);
	}


	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值