P1948 [USACO08JAN]Telephone Lines S
题面大意:
选择一些边使1到n连通,可以使k条边边权为0,求最少花费
sol
花费满足单调性,我们可以二分一个花费,将大于花费的边权标为 1 ,小于花费的边权标为 0,找一条1到n的最短路,如果花费小于等于k,那说明二分的花费可以为答案
将问题变为可行性
#include<bits/stdc++.h>
using namespace std;
const int N = 10010;
int n,m,num;
int tot,head[1010],nex[N<<1],to[N<<1],val[N<<1];
void add(int x,int y,int v){
to[++tot] = y;
val[tot] = v;
nex[tot] = head[x];
head[x] = tot;
}
int dis[1010];
int ins[1010];
bool spfa(int s,int mid,int k){
memset(dis,0x3f,sizeof(dis));
memset(ins,0,sizeof(ins));
queue<int>que;
que.push(s);
ins[s] = 1;
dis[s] = 0;
while(que.size()){
int x = que.front();
que.pop();
ins[x] = 0;
for(int i = head[x];i;i = nex[i]){
int y = to[i];
int v = (val[i] > mid ? 1 : 0);
if(dis[y] > dis[x] + v){
dis[y] = dis[x] + v;
if(ins[y] == 0){
que.push(y);
ins[y] = 1;
}
}
}
}
return dis[n] <= k;
}
int maxn = 0;
int main(){
scanf("%d%d%d",&n,&m,&num);
for(int i = 1;i <= m;i ++){
int x,y,v;scanf("%d%d%d",&x,&y,&v);
add(x,y,v);add(y,x,v);
maxn = max(maxn , v);
}
bool flag = 0;
int l = 0;int r = maxn;
while(l < r){
int mid = (l + r) >> 1;
if(spfa(1,mid,num)) { r = mid;flag = 1; }
else l = mid + 1;
}
if(flag == 1)
printf("%d",l);
else printf("-1");
return 0;
}