【USACO 2008 January Silver】架设电话线 二分答案+最短路

来源:互联网 发布:北京电信网络 编辑:程序博客网 时间:2024/05/22 12:59
这道题其实跟以前做的求所有到终点的路径的最大边的最小值很像,那个问题是用二分来解的,而这道题,无非是增加了一个k条边免费的一个限制。依旧可以使用二分答案的方法解决,在判定是否可行时,只需要判断是否能寻找到一条路径,使得该路径上大于我们二分的这个值的边不超过k条,实质上就是最短路做的一个变形而已,小于二分的值的边可以看做边权为0,大于的可以看做边权为1,直接求最短路看是否小于k即可
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<queue>#define MAX 1009#define inf 1011111111using namespace std;int n,i,m,k;struct wbysr{int to,value;};vector<wbysr>e[MAX];bool check(int x){queue<int>q;int done[MAX]={0},dis[MAX];for(int i=2;i<=n;i++)dis[i]=inf;dis[1]=0;done[1]=1;q.push(1);while(!q.empty()){int now=q.front();q.pop();done[now]=0;for(int j=0;j<e[now].size();j++){if(dis[e[now][j].to]>dis[now]+bool(e[now][j].value>x)){dis[e[now][j].to]=dis[now]+bool(e[now][j].value>x);if(!done[e[now][j].to]){done[e[now][j].to]=1;q.push(e[now][j].to);}}}}return dis[n]<=k;}int main(){scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=m;i++){int a1,a2,a3;scanf("%d%d%d",&a1,&a2,&a3);e[a1].push_back((wbysr){a2,a3});e[a2].push_back((wbysr){a1,a3});}int l=0,r=inf,ans=inf;while(l<=r){int mid=(l+r)/2;if(check(mid)){ans=min(ans,mid);r=mid-1;}elsel=mid+1;}if(ans==inf)printf("-1\n");elseprintf("%d\n",ans);return 0;}

0 0
原创粉丝点击