题目大意:n个点p条边,每条边有权值,让1和n点联通,可以将联通1--n的边选k条免费,
求剩下边权的最大值。
题解:二分一个答案x,大于x的边权设为1,小于等于x的边权设为0,跑最短路。
若从1到n的最短路dis[n]<=k,则可以通过免费k条边,答案为x。
代码:
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #define N 1009 #define M 10009 using namespace std; int n,p,k; int sumedge; int head[N],dis[N],vis[N]; queue<int>q; struct Edge { int x,y,z,nxt; Edge(int x=0,int y=0,int z=0,int nxt=0): x(x),y(y),z(z),nxt(nxt){} }edge[M<<1]; void add(int x,int y,int z) { edge[++sumedge]=Edge(x,y,z,head[x]); head[x]=sumedge; } bool ok(int tp) { while(!q.empty()) q.pop(); memset(dis,0x3f,sizeof(dis)); q.push(1);vis[1]=true;dis[1]=0; while(!q.empty()) { int now=q.front();q.pop(); vis[now]=false; for(int i=head[now];i;i=edge[i].nxt) { int v=edge[i].y; if(dis[v]>dis[now]+(edge[i].z<=tp?0:1)) { dis[v]=dis[now]+(edge[i].z<=tp?0:1); if(!vis[v]) { vis[v]=true; q.push(v); } } } } return dis[n]<=k; } int main() { scanf("%d%d%d",&n,&p,&k); int l=0,r=0,ans=-1; for(int i=1;i<=p;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z);add(y,x,z); r=max(r,z); } while(l<=r) { int mid=(l+r)>>1; if(ok(mid)) ans=mid,r=mid-1; else l=mid+1; } cout<<ans<<endl; return 0; }