题意
要求有向图上一点到另一点的长度不超过p的最短路上的最长的边最长是多少。
分析
不能单纯的跑一边或者两边最短路,可能最短路的情况下边不是最大的。
反向建立图,由终点和起点做两次最短路,然后枚举每一条边,找出最长的边,且加上这条边后,由起点到终点的长度不大于p。
这里最短路可以用各种方法,不想写优先队列。用了bellman-ford
代码
1 #define rep(x,y,z) for(int x=y;x<z;x++) 2 #define drep(x,y,z) for(int x=y;x>=z;x--) 3 #define pb(x) push_back(x) 4 #define mp(x,y) make_pair(x,y) 5 #define clr(x,y) memset(x,y,sizeof(x)) 6 #define fi first 7 #define se second 8 9 #include <iostream> 10 #include <stdio.h> 11 #include <string.h> 12 #include <algorithm> 13 #include <vector> 14 #include <queue> 15 using namespace std; 16 17 const int N = 1e4 + 10; 18 const int inf = 0x3f3f3f3f; 19 20 vector<pair<pair<int,int>,int> > edge[2]; 21 int dis[2][N]; 22 23 void init(){ 24 clr(dis,inf); 25 edge[0].clear(); 26 edge[1].clear(); 27 } 28 29 void slove(int k , int s){ 30 int size = edge[k].size(); 31 dis[k][s] = 0; 32 while(1){ 33 bool ok = 0; 34 rep(i,0,size){ 35 int f = edge[k][i].fi.fi; 36 int r = edge[k][i].fi.se; 37 int w = edge[k][i].se; 38 // 39 if(dis[k][f] + w < dis[k][r]){ 40 dis[k][r] = dis[k][f] + w; 41 ok = 1; 42 } 43 // 44 } 45 if(!ok) break; 46 } 47 } 48 49 void read(int m){ 50 rep(i,0,m){ 51 int u , v , w; 52 scanf("%d %d %d",&u,&v,&w); 53 edge[0].pb(mp(mp(u,v),w)); 54 edge[1].pb(mp(mp(v,u),w)); 55 } 56 } 57 58 int main(){ 59 int t; 60 scanf("%d",&t); 61 rep(tt,1,t+1){ 62 int n , m , s , t , p; 63 scanf("%d %d %d %d %d",&n,&m,&s,&t,&p); 64 init(); 65 read(m); 66 slove(0,s); 67 slove(1,t); 68 int size = edge[0].size(); 69 int ans = -1; 70 rep(i,0,size){ 71 int a = edge[0][i].fi.fi; 72 int b = edge[0][i].fi.se; 73 int w = edge[0][i].se; 74 // 75 if(dis[0][a] + dis[1][b] + w <= p) ans = max(ans,w); 76 //if(dis[1][a] + dis[0][b] + w <= p) ans = max(ans,w); 77 // 78 } 79 printf("Case %d: %d\n",tt,ans); 80 } 81 return 0; 82 }
时间: 2024-11-05 06:04:47