Fire-Fighting Hero

注意:
(1)无向图
(2)对于救火队员来说,到达某一点的最短时间为所有救火队员到达该点的最小值。
也就是说只要有一个救火队员到达该店就行;
优化:
(学长给的优化方法)
由于救火队员有多个,我们需要求出每个救火队员到达某一点的时间,再求出最小值;但是救火队员只要有一个到达该点即可,所以,可以在救火队员之间加上权值为0的边,这样只需要求出来一个救火队员到达其它点的时间即可。
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int num=1e6+10;
const int num_p=1010;
const LL inf=1e18;
int n,e,s,k;
LL c;
int team[num_p];

struct node
{
	int v,next;
	LL w;
	node (){};//c++ÀïµÄ¹¹Ô캯Êý
	node(int a,LL b)
	{
		v=a;w=b;
	}
	
	bool operator <(const node & s) const//ʹÓÃÁËÓÅÏȶÓÁУ¬¶ÔµãÅÅÐò£¬¾àÀëÆðµã½üµÄÔÚÇ°
	{
	return w > s.w;
	}
}edge[num];
int head[num],cnt;//¼Ç¼ÒÔµ±Ç°½ÚµãΪÆðµãµÄ×îеÄÒ»Ìõ±ß
void int_i()
{
	cnt=0;
	memset(head,0,sizeof(head));
	return ;
}
void addedge(int a,int b,LL c)
{
	edge[++cnt].v=b;
	edge[cnt].w=c;
	edge[cnt].next=head[a];
	head[a]=cnt;
	return ;
}
LL dijkstra(int s,int f)//sµãµÀÆäËüµãµÄ¾àÀ룻 
{
	LL dis[num_p];
	int book[num_p];//±ê¼ÇÄĸöµãÒѾ­±»ÊÕËõ¹ýÁË
	for(int i=1;i<=n;i++)
	{
		dis[i]=inf;
		book[i]=0;
	}
	
	dis[s]=0;
	priority_queue<node>q;
	q.push(node(s,0));

	while(!q.empty())
	{
		node x=q.top();q.pop();
		if(book[x.v])
		continue;
		book[x.v]=1;
		
		for(int i=head[x.v];i;i=edge[i].next)
		{
			int y=edge[i].v;
			if(dis[y] > x.w + edge[i].w)
			{
				dis[y]=x.w + edge[i].w;
				q.push(node(y,dis[y]));
			}
		}
	}
	
	//
	LL ans=0;
	for(int i=1;i<=n;i++)
	{
	//	if(i!=s)
		ans=max(ans,dis[i]);
	}
	return ans;
	
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int_i();
		scanf("%d%d%d%d%lld",&n,&e,&s,&k,&c);
		
		for(int i=1;i<=k;i++)
		{
			scanf("%d",&team[i]); 
		} 	
		int u,v;
		LL w;
		for(int i=1;i<=e;i++)
		{
			scanf("%d%d%lld",&u,&v,&w);
			addedge(u,v,w);
			addedge(v,u,w);
		}
		
		LL ans=dijkstra(s,0);
		LL ans2=0;
		
		for(int i=1;i<=k;i++)
		for(int j=i+1;j<=k;j++)
		{
			addedge(team[i],team[j],0);
			addedge(team[j],team[i],0);
		}
		
		ans2=dijkstra(team[1],0);
		
		if(ans <= ans2*c) {
			printf("%lld\n",ans);
		}
		else {
			printf("%lld\n",ans2);
		}
	}
	return 0;	
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值