P1948 [USACO08JAN]电话线Telephone Lines
传送门
思路:
二分+最短路径:可以将长度小于等于 mid 的边视为长度为 0 的边,大于 mid 的边视为长度为 1 的边,最后用 dijkstra 检查 d [ n ] 是否小于等于 k 即可。
标程:
#include<cstring> #include<queue> #include<cstdio> #include<iostream> #include<vector> #include<fstream> #include<algorithm> #include<cstdlib> #include<cmath> #include<stack> #include<map> #include<set> #include<deque> #include<string> using namespace std; #define maxn 100100 #define INF 0x3f3f3f3f priority_queue<pair< int,int >,vector<pair<int,int> >,greater<pair<int,int > > > q; struct hh { int u,v,w,nex; }t[maxn<<1]; int d[maxn<<1],head[maxn<<1],jla[maxn<<1];//jla记录每条边的边长 int n,m,p,s=1,cnt=0,ans=INF;//ans记录答案 bool vis[maxn<<1]; inline int read() { int kr=1,xs=0; char ls; ls=getchar(); while(!isdigit(ls)) { if(ls=='-') kr=-1; ls=getchar(); } while(isdigit(ls)) { xs=(xs<<1)+(xs<<3)+(ls^48); ls=getchar(); } return kr*xs; } inline void add(int x,int y,int z) { t[++cnt].u=x; t[cnt].v=y; t[cnt].w=z; t[cnt].nex=head[x]; head[x]=cnt; }//链式前向星加边 inline bool dijkstra(int now) { for(int i=1;i<=n;i++) { d[i]=INF; vis[i]=false; } d[s]=0; q.push(make_pair(d[s],s)); while(!q.empty()) { int k=q.top().second; q.pop(); if(vis[k]) continue; else { vis[k]=true; for(int i=head[k];i!=-1;i=t[i].nex) { if(t[i].w>now) if(d[t[i].v]>d[k]+1) { d[t[i].v]=d[k]+1; q.push(make_pair(d[t[i].v],t[i].v)); }//如果t[i].v的边大于当前二分的答案,那么就要使用一次名额 if(t[i].w<=now) if(d[t[i].v]>d[k]) { d[t[i].v]=d[k]; q.push(make_pair(d[t[i].v],t[i].v)); }//如果t[i].v的边不大于当前二分的答案,那么就无需使用名额,直接松弛操作 } } } if(d[n]>p) return false;//如果到达n的次数大于免费的次数限制,那么当前答案不可行 return true;//反之,则可行 } int main() { n=read();m=read();p=read(); for(int i=1;i<=n;i++) head[i]=-1; int xx,yy,zz; for(int i=1;i<=m;i++) { xx=read();yy=read();zz=read(); add(xx,yy,zz); add(yy,xx,zz); jla[i]=zz; } sort(jla+1,jla+m+1);//将所有的边从小到大排序,为二分做准备 if(dijkstra(0)) { printf("0\n"); return 0; } if(!dijkstra(jla[m])) { printf("-1\n"); return 0; }//两个特判,,, int l=1,r=m; while(l<=r) { int mid=l+r>>1;//二分查找 if(dijkstra(jla[mid])) { ans=min(ans,jla[mid]); r=mid-1; } else l=mid+1; } printf("%d\n",ans);//输出答案 return 0; }