1. 程式人生 > >bzoj 1614 Telephone Lines

bzoj 1614 Telephone Lines

pan 枚舉 log edge can node algorithm str ret

最近最小生成樹題目做傻了,看到題目的第一感覺就是最小生成樹。。。

後面才發現是求最短路。

正解算法: 二分+spfa

二分枚舉一個花費的錢(除去k對免費的),spfa跑最短路,如果最短路的長度大於二分值則說明是免費的。

如果免費的對數<=k 那麽說明這個值是可行的 還得記錄一下答案,再r=mid-1。

否則相反 l=mid+1

註意:別像我一樣SPFA忘記寫判環而WA。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <queue>
 4 #include <cstring>
 5
6 7 struct node{ 8 int u,v,w,next; 9 node(){} 10 node(int _u,int _v,int _w,int _next){ 11 u = _u; 12 v = _v; 13 w = _w; 14 next = _next; 15 } 16 }Edge[20005]; 17 18 int n,p,k,Count,head[10005]; 19 int x,y,z,dis[1005],ans=-1; 20 bool inque[1005
]; 21 22 void AddEdge(int u,int v,int w){ 23 Count++; 24 Edge[Count]=node(u,v,w,head[u]); 25 head[u]=Count; 26 } 27 28 bool spfa(int x){ 29 memset(dis,0x3f3f3f3f,sizeof(dis)); 30 memset(inque,0,sizeof(inque)); 31 std::queue<int>Q; 32 Q.push(1); 33 int
s; 34 inque[1]=1; 35 dis[1]=0; 36 while( !Q.empty() ){ 37 int now = Q.front(); 38 Q.pop(); 39 inque[now]=0; 40 for(int i=head[now];i;i=Edge[i].next){ 41 if(Edge[i].w>x) s=dis[now]+1; 42 else s = dis[now]; 43 if(s<dis[Edge[i].v]){ 44 dis[Edge[i].v] = s; 45 if(!inque[Edge[i].v]){ 46 Q.push(Edge[i].v); 47 inque[Edge[i].v]=1; 48 } 49 } 50 } 51 } 52 //printf("%d\n",dis[n]); 53 if(dis[n]<=k) return true; 54 return false; 55 } 56 57 int main(){ 58 scanf("%d%d%d",&n,&p,&k); 59 for(int i=1;i<=p;i++){ 60 scanf("%d%d%d",&x,&y,&z); 61 AddEdge(x,y,z); 62 AddEdge(y,x,z); 63 } 64 int l = 0,r = 1000000; 65 while(l<=r){ 66 int mid = (l+r)>>1; 67 if( spfa(mid) ){ 68 ans = mid; 69 r = mid - 1; 70 } 71 else l = mid + 1; 72 } 73 printf("%d\n",ans); 74 return 0; 75 }

bzoj 1614 Telephone Lines