luogu#P1462 通往奥格瑞玛的道路
作者:互联网
题意:
给出一张有 \(n\) 个点, \(m\) 条边的无向图
每个点上有一个点权 \(f[i]\) ,表示经过这个点需要交 \(f[i]\) 的费用。,每条边上有一个边权 \(C[i]\) ,表示经过这条边需要扣除 \(C[i]\) 的血量
求能从起点 \(1\) 到达 \(n\) 的情况下交费最多一次的最小值
解法:
先判断一次假设血量为最大血量+ 时是否可以走通
然后二分每次交的最大费用 \(w\) ,用dijkstra求从源点到终点需要的最小血量
==数据比较大需要开long long==
#include<iostream>
#include<queue>
#include<cstring>
#define ll long long
#define M 50005
#define N 10005
using namespace std;
struct Edge{ll next,to,dis;}edge[M<<1];
struct node{ll dis,u;bool operator < (const node &x)const {return x.dis<dis;}};
ll n_e,n,m,head[N],hp,c[N],mxm,dis[N];
bool vis[N];
bool dij(ll s,ll t,ll w);
inline void addedge(ll from,ll to,ll dis);
void init();
int main()
{
ll l,r;
init();
if(dij(1,n,1000000001)==0)
{
cout<<"AFK";
return 0;
}
l=0; r=mxm;
while(l<=r)
{
int mid=l+r>>1;
if(dij(1,n,mid))
r=mid-1;
else
l=mid+1;
}
cout<<l;
return 0;
}
bool dij(ll s,ll t,ll w)
{
if(c[s]>w||c[t]>w)
return 0;
memset(dis,0x7f,sizeof(dis));
memset(vis,0,sizeof(vis));
priority_queue<node> q;
dis[s]=0;
q.push((node){0,s});
while(!q.empty())
{
node tmp=q.top();
q.pop();
ll now=tmp.u;
if(vis[now])
continue;
vis[now]=1;
for(int i=head[now];i;i=edge[i].next)
{
int v=edge[i].to;
if(dis[v]>dis[now]+edge[i].dis)
{
dis[v]=dis[now]+edge[i].dis;
if(!vis[v]&&c[v]<=w)
q.push((node){dis[v],v});
}
}
}
if(dis[t]<=hp)
return 1;
else
return 0;
}
inline void addedge(ll from,ll to,ll dis)
{
edge[++n_e].next=head[from];
edge[n_e].to=to;
edge[n_e].dis=dis;
head[from]=n_e;
}
void init()
{
cin>>n>>m>>hp;
mxm=-1;
for(int i=1;i<=n;i++)
{
ll w;
cin>>w;
mxm=max(mxm,w);
c[i]=w;
}
for(int i=1;i<=m;i++)
{
ll u,v,w;
cin>>u>>v>>w;
if(u==v)
continue;
addedge(u,v,w);
addedge(v,u,w);
}
}
标签:瑞玛,int,luogu,P1462,vis,edge,long,now,dis 来源: https://www.cnblogs.com/nenT/p/11700352.html