luogu P1948 [USACO08JAN]电话线Telephone Lines

北城余情 提交于 2019-12-10 09:13:35

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

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!