题意:
一个联通的无向图,通过每一个点会收费,通过每一条边会减少血量。求能到达终点 (即血量到终点还不为0) 的各个路径上,收费最高的最小值。
思路:
首先一开始的思路是找到所有能到终点的路径,然后取每条路径上的最高收费,比较取最小值,数据量大,pass;再思考,他求的是最大的最小值,那我们可以想到二分,去二分路径上的最高消费,然后判断这样能不能走到终点。判断的函数就可以考虑Spfa和Dijkstra了,只要将这两个在跑的时候略加改变即可,如果通向的那个点,最高消费大于你枚举的最高消费,就不做考虑。最后pd一下到终点的需要消耗的最小血量是不是大于你的血量b。
这个题在同样的读入方式下Spfa是跑的比Dijkstra快的;
Spfa:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int inf=-0x3f3f3f3f;
const int maxn=1e5+5;
int dist[maxn];
bool vis[maxn];
int cost[maxn];
int n,m,b;
struct edge {
int to;
int w;
};
vector<edge> ee[maxn];
bool spfa(int maxmoney) {
memset(dist,0x3f,sizeof(dist));
memset(vis,false,sizeof(vis));
dist[1]=0;
vis[1]=true;
queue<int> q;
q.push(1);
while(!q.empty()) {
int np=q.front();
q.pop();
vis[np]=false;
for(int i=0; i<(int)ee[np].size(); ++i) {
edge tt=ee[np][i];
if(cost[tt.to]<=maxmoney) {
if(dist[tt.to]>dist[np]+tt.w) {
dist[tt.to]=dist[np]+tt.w;
if(vis[tt.to]==false) {
q.push(tt.to);
vis[tt.to]=true;
}
}
}
}
}
if(dist[n]>=b) return false;
else return true;
}
int main() {
cin>>n>>m>>b;
int le=INF,ri=inf;
for(int i=1;i<=n;++i){
cin>>cost[i];
le=min(le,cost[i]);
ri=max(ri,cost[i]);
}
int x,y,z;
for(int i=1;i<=m;++i){
cin>>x>>y>>z;
ee[x].push_back(edge{y,z});
ee[y].push_back(edge{x,z});
}
if(!spfa(ri)){
cout<<"AFK"<<endl;
}
else{
while(le<ri){
int mid=(le+ri)>>1;
if(spfa(mid)){//可达
ri=mid;
}
else{//不可达
le=mid+1;
}
}
cout<<le<<endl;
}
return 0;
}
Dijkstra:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int inf=-0x3f3f3f3f;
const int maxn=1e5+5;
int dist[maxn];
bool vis[maxn];
int cost[maxn];
int n,m,b;
struct node {
ll p; //当前点
ll dis; //起始点到该点的最短距离
node(ll np=0,ll ndis=0) {
p=np,dis=ndis;
}
bool operator <(const node& x)const {
return dis>x.dis;
}
};
struct edge {
int to;
int w;
};
vector<edge> ee[maxn];
bool Dijkstra(int maxmoney) {
memset(dist, 0x3f, sizeof(dist));
memset(vis, false, sizeof(vis));
dist[1]=0;
priority_queue<node> q;
q.push(node(1,0));
while(!q.empty()) {
node tmp=q.top();
q.pop();
int np=tmp.p;
if(vis[np])
continue;
else {
vis[np]=1;
for(int i=0; i<ee[np].size(); ++i) {
edge ne=ee[np][i];
ll nto=ne.to;
ll nw=ne.w;
if(cost[nto]<=maxmoney) {
if(dist[nto]>dist[np]+nw) {
dist[nto]=dist[np]+nw;
q.push(node(nto,dist[nto]));
}
}
}
}
}
if(dist[n]>=b) return false;
else return true;
}
int main() {
cin>>n>>m>>b;
int le=INF,ri=inf;
for(int i=1; i<=n; ++i) {
cin>>cost[i];
le=min(le,cost[i]);
ri=max(ri,cost[i]);
}
int x,y,z;
for(int i=1; i<=m; ++i) {
cin>>x>>y>>z;
ee[x].push_back(edge {y,z});
ee[y].push_back(edge {x,z});
}
if(!Dijkstra(ri)) {
cout<<"AFK"<<endl;
} else {
while(le<ri) {
int mid=(le+ri)>>1;
if(Dijkstra(mid)) {//可达
ri=mid;
} else { //不可达
le=mid+1;
}
}
cout<<le<<endl;
}
return 0;
}
版权声明:本文为TDD_Master原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。