https://www.acwing.com/problem/content/342/
题意
给你一个图
你可以选择一条1号点到N号点的路径,并指定路径上不超过K条边,
我们可以指定这个路径中k条边的权值为0,然后我们只需要花费这条路中剩下最大的那一条边权就行
问最大边权的最小值是多少
扩展:
拆点,分层图
思想回顾
能不能二分
答案一定在一个区间内
答案的左右两个区间 只有一个区间满足答案的要求
范围0~ 1e6+1
如果不连通和连通的都有可能二分到1e6 如果我们然让1e6+1 如果是连通的不可能取到1e6+1,如果是不连通的那么取到1e6+1
最短路背模板就像你学英语需要背单词一样,
code:
#include <bits/stdc++.h>
using namespace std;
const int N = 1010, M = 20010;
int n,m,k;
int h[N],e[M],w[M],ne[M],idx;
int dist[N];
int st[N]; /// 双端队列 形如dij 所以需要打标记
deque<int> q;
void add(int a,int b,int c)
{
e[idx] =b,w[idx] = c,ne[idx]= h[a],h[a] = idx++;
}
bool check(int bound)
{
memset(dist,0x3f,sizeof dist);
memset(st,0,sizeof st);
q.push_back(1);
dist[1] = 0;
while(q.size())
{
int t = q.front();
q.pop_front();
if(st[t]) continue;
st[t] = true;
for(int i =h[t];~i;i=ne[i])
{
int j= e[i];
int x=w[i] >bound; ///找出大于x的边
if(dist[j] > dist[t] +x)
{
dist[j] = dist[t] +x;
if(!x) q.push_front(j);
else q.push_back(j);
}
}
}
return dist[n]<=k;
}
int main()
{
cin>>n>>m>>k;
memset(h,-1,sizeof h);
while( m -- )
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
int l=0,r=1e6+1;
while( l<r )
{
int mid =l+r>>1;
if(check(mid)) r= mid;
else l=mid+1;
}
if(r == 1e6+1)
cout<<-1<<endl;
else
cout<<r<<endl;
}