luogu P1948 [USACO08JAN]电话线Telephone Lines

1 篇文章 0 订阅
1 篇文章 0 订阅

原题传送门:Luogu P1948

题意:给出一张图,要求在1到n的某个路径上去掉k条边,使得剩下的边中最大值最小

 

题意分析完之后,看那个使最大值最小显然是二分答案。

然后至于check,可以在遍历的时候把边权小于等于mid的值都视作0,大于的都视作1

然后进行SPFA,判断dis[n]是否小于等于k就行了

附代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;

const int MAXN=2e4+5;
struct edge{
	int x,y,c;
	bool operator <(const edge &b)const{
		return c<b.c;
	}
}s[MAXN];
int n,m,tot,x,y,c,dis[MAXN],inS[MAXN],p,k,cnt,ans;
int node[MAXN],nex[MAXN],A[MAXN],cos[MAXN];

void add(int x,int y,int c){
	node[++tot]=y;nex[tot]=A[x];A[x]=tot;cos[tot]=c;
}

bool chk(int rec){
	for (int i=1;i<=n;i++) dis[i]=2333333,inS[i]=0;
	queue <int> q;
	q.push(1);dis[1]=0;
	while (!q.empty()){
		int x=q.front();q.pop();
		int j=A[x];inS[x]=0;
		while (j!=0){
			int e=node[j];
			int tmp=(cos[j]>rec);
			if (dis[e]>dis[x]+tmp){
				dis[e]=dis[x]+tmp;
				if (!inS[e]) inS[e]=1,q.push(e);
			}
			j=nex[j];
		}
	}
	if (dis[n]>k) return 0;
	else return 1;
}

int main(){
	cin>>n>>p>>k;
	for (int i=1;i<=p;i++){
		cin>>x>>y>>c;
		add(x,y,c);add(y,x,c);
	}
	int l=0,r=1e6+5;
	while (l<r){
		int mid=(l+r)>>1;
		if (chk(mid)) r=mid;
		else l=mid+1; 
	}
	if (r>1e6) cout<<-1<<endl;
	else cout<<l<<endl;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值