在郊区有 N 座通信基站,P 条 双向 电缆,第 i 条电缆连接基站 Ai 和 Bi。
特别地,1 号基站是通信公司的总站,N 号基站位于一座农场中。
现在,农场主希望对通信线路进行升级,其中升级第 i 条电缆需要花费 Li。
电话公司正在举行优惠活动。
农产主可以指定一条从 1 号基站到 N 号基站的路径,并指定路径上不超过 K 条电缆,由电话公司免费提供升级服务。
农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。
求至少用多少钱可以完成升级。
输入格式
第 1 行:三个整数 N,P,K。
第 2..P+1行:第 i+1行包含三个整数 Ai,Bi,Li。
输出格式
包含一个整数表示最少花费。
若 1 号基站与 N 号基站之间不存在路径,则输出 −1。
数据范围
0≤K<N≤1000,
1≤P≤10000,
1≤Li≤1000000
输入样例:
5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6
输出样例:
4
二分法二分答案+check函数遍历图
对于图的处理方法(当w>mid时就权重为1,否则就为0,最后路径长度就是去掉了几条边,若>k怎证明不符合条件return false)
遍历图有两种:
一种为迪杰斯特拉求最短路径:
#include <bits/stdc++.h>
using namespace std;
const int N=1010;
typedef pair<int,int> PII;
struct node{
int v,w;
};
vector<node>adj[N];
int st[N],d[N];
int n,p,k;
bool check(int mid)//其实是迪杰斯特拉
{
priority_queue<PII,vector<PII>,greater<PII> >q;
memset(st,0,sizeof st);
memset(d,0x3f,sizeof d);
d[1]=0;
q.push({0,1});
while(q.size())
{
int u=q.top().second;
q.pop();
if(st[u]) continue;
if(u==n)
{
if(d[u]>k)return false;
else return true;
}
st[u]=1;
for(int i=0;i<adj[u].size();i++)
{
int v=adj[u][i].v,w=adj[u][i].w;
if(w>mid) w=1;
else w=0;
if(d[v]>w+d[u])
{
d[v]=w+d[u];
q.push({w+d[u],v});
}
}
}
return false;
}
int main()
{
cin>>n>>p>>k;
while(p--)
{
int a,b,l;
cin>>a>>b>>l;
adj[a].push_back({b,l});
adj[b].push_back({a,l});
}
int l=0,r=1e6+10,mid;
while(l<r)
{
mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
if(l>1e6)cout<<-1;
else cout<<l;
return 0;
}
另一种bfs+双端队列(加快遍历):
#include <iostream>
#include <vector>
#include <deque>
using namespace std;
const int N=7000;
const int INF=0x7f7f7f7f;
struct node{
int v,dis;
};
vector<node> adj[N];
deque<int> q;
int d[N];
bool vis[N]={false};
int n,s=1,k;//一条从 1 号基站到 N 号基站的路径,并指定路径上不超过 K 条电缆
bool check(int mid)//用了bfs
{
fill(vis,vis+n+1,false);
fill(d,d+n+1,INF);
q.push_back(s);
vis[s]=true;
d[s]=0;
while(!q.empty())
{
int u=q.front();
q.pop_front();
for(int i=0;i<adj[u].size();i++)
{
int v=adj[u][i].v;
if(!vis[v])
{
vis[v]=true;
if(adj[u][i].dis>mid)
q.push_back(v);
else
q.push_front(v);
}
if(adj[u][i].dis>mid)
d[v]=min(d[v],d[u]+1);
else
d[v]=min(d[v],d[u]);
}
}
if(d[n]<=k)
return true;
else
return false;
}
int main()
{
int p;
cin>>n>>p>>k;
node a;
int n2,n1;
int l=0,r=1000001;
for(int i=0;i<p;i++)
{
cin>>n2;
cin>>a.v>>a.dis;
adj[n2].push_back(a);
n1=a.v;
a.v=n2;
adj[n1].push_back(a);
}
int mid=(l+r)>>1;
while(l<r)
{
if(check(mid))
r=mid;
else
l=mid+1;
mid=(l+r)>>1;
}
if(r==1000001)
cout<<"-1";
else
cout<<l;
return 0;
}