原题传送门: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;
}
来源:CSDN
作者:碳碳双键
链接:https://blog.csdn.net/qq_24941253/article/details/103463562