最近最小生成树题目做傻了,看到题目的第一感觉就是最小生成树。。。
后面才发现是求最短路。
正解算法: 二分+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 }
时间: 2024-10-26 07:59:08