题目大意
有一个由n个点,m条边组成的无环无向图,题目保证是连通图,现在每个点代表一个着火点,有一个消防英雄和k个消防队伍比赛救火,他们的具体位置输入时会给出,谁的分数低谁就获胜,分数的定义如下:
消防英雄:到每个着火点的最短路中的最大值除以题目中给出的C,最后为了避免出现浮点数,消防英雄除以C,变成消防队伍乘以C即可,爆不了int。
消防队伍:从k个队伍中选择最优的一个消防队伍(即下半句话中描述的分数最小的队伍),也是取到每个着火点的最短路中的最大值
如果消防英雄获胜,输出消防英雄的原分数,如果消防队伍获胜,输出消防队伍的原分数,如果平局,算是消防英雄获胜
这题我知道是Dijkstra,但是题目没看懂,真的难受。其中1和4是已经确定了消防车的其实地点,所以1到4和4到1都是0
因为消防车没有固定点出发,所以从0开始,而英雄已经固定从s点开始
有一点没有弄懂:为什么INF定义为0x3f3f3f3f就可以,定义成999999999就输出为0?
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 1010
#define INF 0x3f3f3f3f
int T,v,e,s,k,c;
struct Node{
int p;
int val;
Node(int _p,int _val):p(_p),val(_val){}
};
vector<Node>G[maxn];
void insert(int st,int en,int len){
G[st].push_back(Node(en,len));
}
int dis[maxn];
int vis[maxn];
int dijkstra(int st){
queue<int>q;
memset(vis,0,sizeof(vis));
memset(dis,INF,sizeof(dis));
q.push(st);
dis[st]=0;
while(!q.empty()){
int x=q.front();
q.pop();
vis[x]=0;
for(int i=0;i<G[x].size();i++){
int p=G[x][i].p;
if(dis[p]>dis[x]+G[x][i].val){
dis[p]=dis[x]+G[x][i].val;
if(!vis[p]){
q.push(p);
vis[p]=1;
}
}
}
}
return 0;
}
int st,en,len;
int main(){
cin>>T;
while(T--){
for(int i=0;i<maxn-2;i++)
G[i].clear();
cin>>v>>e>>s>>k>>c;
for(int i=0;i<k;i++){
cin>>st;
insert(0,st,0);
}
for(int i=0;i<e;i++){
cin>>st>>en>>len;
insert(st,en,len);
insert(en,st,len);
}
//因为消防车没有出发地点,直接用0就行了
dijkstra(0);
int ans1=0,ans2=0;
for(int i=1;i<=v;i++)
ans1=max(ans1,dis[i]);
//英雄是从s出发
dijkstra(s);
for(int i=1;i<=v;i++)
ans2=max(ans2,dis[i]);
//这里比较如果用除的话不太准确,所以用ans1*c
if(ans1*c>=ans2)
cout<<ans2<<endl;
else
cout<<ans1<<endl;
}
return 0;
}