AcWing 340. 通信线路 题解(二分+双端队列BFS求最短路)

35 篇文章 0 订阅
17 篇文章 0 订阅

AcWing 340. 通信线路
y总说有noip提高组水平,确实题意转换比较难,想找到解法也难,希望自己再努力努力某一天可以只凭自己写出这种水平的题
解题思路:二分+双端队列BFS求最短路,思维转换比较难,几个思维的拐弯点在:①找合适的小于k的值x,用二分。②在判断x是否合适时,可以用双端队列找最短路
请添加图片描述

#include<bits/stdc++.h>

using namespace std;

const int N = 1e3 + 10, M = 2e4 + 10, INF = 0x3f3f3f3f;

int h[N], ne[M], e[M], w[M], idx;
bool st[N];
deque<int>q;
int n, m, p, k;
int dist[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){  //对边权值只有0/1的图用双端队列广搜找最短路 
	memset(st, 0, sizeof st);
	memset(dist, 0x3f, sizeof dist);
	
	dist[1] = 0;
	q.push_front(1);
	
	while(q.size()){
		int op = q.front();
		q.pop_front();
		
		if(st[op]) continue;
		st[op] = true;
		
		for(int i = h[op]; ~i; i = ne[i]){
			int j = e[i], v = w[i] > bound;
			if(dist[j] > dist[op] + v){
				dist[j] = dist[op] + v;
				if(!v) q.push_front(j);
				else q.push_back(j);
			} 
		}
	}
	return dist[n] <= k;  //返回图中边权值大于bound的边数量是否大于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);
	}
	
	//二分找到合适的值mid 
	//合适的值mid是指有mid条边的权值被赋为0时,可以找到最短路
	//这里我一直有一个疑惑是为什么二分出的mid一定是图中存在的权值
	//看了别的大佬详细的解释明白了
	//①第一种理解,如果mid不是图中存在的权值,那么本次check的结果和上次check返回的结果相同,二分不会停止
	//②第二种理解,二分的本质是找到最小值,如果mid不是图中存在的边权值,那么一定存在比他小的是边权值的数,二分会继续,直到找到最小的符合条件的值
	//总得来说一句话,二分找的是最值,而不是合适就行 
	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) r = -1;
	cout<<r<<endl;
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值