luogu P1948 [USACO08JAN]电话线Telephone Lines

原题传送门: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;
}

 

发布了14 篇原创文章 · 获赞 0 · 访问量 786
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览