题意:
题目描述得挺隐晦。但是本质就一句话:求一条"最短路":第k+1大的边最小的"最短路"。
思路:
二分加最短路判定。
最答案进行二分。然后按照二分的值用0,1处理整个图:
将比二分值大的边都置为1,将比二分值小的边都置位0。然后进行找1到n的最短路,如果值小于K,则这个二分值满足题意。
再继续二分,直到找到最优解。
#include<iostream> #include<vector> #include<string> #include<queue> #include<algorithm> #define llong long long #define Min(a,b) (a<b?a:b) #define Max(a,b) (a>b?a:b) #define Abs(a) ((a)>0?(a):-(a)) #define Mod(a,b) (((a)-1+(b))%(b)+1) using namespace std; const int N=1005; const int M=10005; const int inf=1e10; int n,m,K,k; int data[M][3]; struct { int v,next,w; }edge[M<<1]; int edgehead[N]; bool vis[N]; int d[N]; void addedge(int u,int v,int w) { edge[k].v=v; edge[k].w=w; edge[k].next=edgehead[u]; edgehead[u]=k++; } bool OK(int value) { queue<int> que; k=1; memset(edgehead,0,sizeof(edgehead)); memset(edge,0,sizeof(edge)); memset(vis,0,sizeof(vis)); for(int i=1;i<=m;i++) { if(data[i][2]<=value) { addedge(data[i][0],data[i][1],0); addedge(data[i][1],data[i][0],0); } else { addedge(data[i][0],data[i][1],1); addedge(data[i][1],data[i][0],1); } } for(int i=1;i<=n;i++) d[i]=inf; que.push(1); vis[1]=true; d[1]=0; while(!que.empty()) { int now=que.front(); que.pop(); vis[now]=false; for(int i=edgehead[now];i;i=edge[i].next) { int v=edge[i].v; int w=edge[i].w; if(d[v]>d[now]+w) { d[v]=d[now]+w; if(!vis[v]) { que.push(v); } } } } if(d[n]<=K) return true; else return false; } int main() { scanf("%d%d%d",&n,&m,&K); int l,r,rr=0,mid; for(int i=1;i<=m;i++) { scanf("%d%d%d",data[i],data[i]+1,data[i]+2); rr=max(rr,data[i][2]); } l=0,r=rr+1; while(l<r) { mid=(l+r)>>1; if(OK(mid)) { r=mid; } else { l=mid+1; } } if(l<=rr) printf("%d\n",l); else printf("-1\n"); return 0; }