POJ - 3662 Telephone Lines
题目描述
到 n n n有 k k k条边可以免费升级,因此只需要求 1 1 1~ N N N的所有路径中第 k k k + 1 1 1大的值的最小值,是最大最小值模型,因此可以使用二分求解
对于区间 [ 0 , 1000001 ] [0,1000001] [0,1000001]中的某一个点 x x x:
-
- c h e c k ( x ) check(x) check(x)函数表示 : : :从 1 1 1走到 N N N,最少经过的长度大于 x x x的边数的数量是否小于等于 k k k,若是则返回 t r u e true true,否则返回 f a l s e false false
-
- 求出从 1 1 1到 N N N最少经过几条长度大于 x x x的边可以分类成:
- 如果边大于 x x x,则边权看成 1 1 1
- 如果边长小于等于 x x x,则边权看成 0 0 0
#include<iostream>
#include<cstring>
#include<deque>
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];
bool st[N];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);deque<int> q;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],x=w[i]>bound;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;return 0;
}