P1948 [USACO08JAN]電話線Telephone Lines(二分答案+最短路)
阿新 • • 發佈:2018-12-16
思路
考慮題目要求求出最小的第k+1大的邊權,想到二分答案
然後二分第k+1大的邊權wx
把所有邊權<=wx的邊權變為0,邊權>wx的邊權變為0,找出最短路之後,如果dis[T]<=k,則答案可行,反之則不可行
似乎有dp解法的樣子,真神奇
程式碼
#include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; int dis[1100],u[11000<<1],v[11000<<1],w[11000<<1],n,p,k,fir[11000<<1],nxt[11000<<1],cnt; void addedge(int ui,int vi,int wi){ ++cnt; u[cnt]=ui; v[cnt]=vi; w[cnt]=wi; nxt[cnt]=fir[ui]; fir[ui]=cnt; } bool check(int mid){ memset(dis,0x3f,sizeof(dis)); deque<int> q; q.push_back(1); dis[1]=0; while(!q.empty()){ int x=q.front(); q.pop_front(); for(int i=fir[x];i;i=nxt[i]){ if(dis[x]+(w[i]>mid)<dis[v[i]]){ dis[v[i]]=dis[x]+(w[i]>mid); if(w[i]>mid) q.push_back(v[i]); else q.push_front(v[i]); } } } return dis[n]<=k; } int main(){ scanf("%d %d %d",&n,&p,&k); for(int i=1;i<=p;i++){ int a,b,c; scanf("%d %d %d",&a,&b,&c); addedge(a,b,c); addedge(b,a,c); } int l=0,r=1000100,ans=-1; while(l<=r){ int mid=(l+r)>>1; if(check(mid)){ ans=mid; r=mid-1; } else l=mid+1; } printf("%d",ans); return 0; }