在加权无向图上求出一条从1号结点到n号结点的路径,使路径上第k+1大的边权尽量小。
解读:二分搜索答案,求>mid的边的数量最好是k,否则就少一点点
#include<cstdio> #include<cstdlib> #include<vector> #include<queue> #include<cstring> using namespace std; int n,m,k; const int N=1003; struct node { int v,w; node(int vv,int ww) { v=vv,w=ww; } node(){} }; vector <node > g[N]; int sz[N]; struct nd { int v,d,cnt; bool operator < (const nd & o) const { return d>o.d; } nd(int vv,int dd,int c) { v=vv,d=dd,cnt=c; } nd(){} }; priority_queue <nd> q; int dis[N][1003],mx;//就是求小于mid的边是不是 大于等于 k bool check(int mid) { while(!q.empty() ) q.pop() ; memset(dis,-1,sizeof(dis)); dis[1][0]=0,q.push(nd(1,0,0)); int ans=k+1; while(!q.empty() ) { nd t=q.top() ;q.pop() ; if(t.d !=dis[t.v ][t.cnt ]) continue; if(t.v ==n) { ans=t.cnt ; break; } for(int i=0;i<sz[t.v ];i++) { int nx=g[t.v ][i].v ,dd,stp=t.cnt ; if(g[t.v ][i].w > mid) dd=dis[t.v ][stp],stp++; else dd=max(g[t.v ][i].w ,dis[t.v ][stp]); if(stp>k) continue; if(dd < dis[nx][stp] || dis[nx][stp]==-1) { dis[nx][stp]=dd; q.push(nd(nx,dd,stp)); } } } return ans<=k; } int main() { scanf("%d%d%d",&n,&m,&k); int u,v,w; while(m--) { scanf("%d%d%d",&u,&v,&w); g[u].push_back(node(v,w)); g[v].push_back(node(u,w)); } for(int i=1;i<=n;i++) sz[i]=g[i].size() ; int l=0,r=1<<30,ans; if(!check(r)) printf("-1\n"); else { while(l<r) { int mid=(l+r)>>1; if(check(mid)) r=mid; else l=mid+1; } printf("%d\n",l); } return 0; }