CODEVS——T1183 泥泞的道路
题目描述 Description
CS有n个小区,并且任意小区之间都有两条单向道路(a到b,b到a)相连。因为最近下了很多暴雨,很多道路都被淹了,不同的道路泥泞程度不同。小A经过对近期天气和地形的科学分析,绘出了每条道路能顺利通过的时间以及这条路的长度。
现在小A在小区1,他希望能够很顺利地到达目的地小区n,请帮助小明找出一条从小区1出发到达小区n的所有路线中(总路程/总时间)最大的路线。请你告诉他这个值。
输入描述 Input Description
第一行包含一个整数n,为小区数。
接下来n*n的矩阵P,其中第i行第j个数表示从小区i到小区j的道路长度为Pi,j。第i行第i个数的元素为0,其余保证为正整数。
接下来n*n的矩阵T,第i行第j个数表示从小区i到小区j需要的时间Ti,j。第i行第i个数的元素为0,其余保证为正整数。
输出描述 Output Description
写入一个实数S,为小区1到达n的最大答案,S精确到小数点后3位。
样例输入 Sample Input
3
0 8 7
9 0 10
5 7 0
0 7 6
6 0 6
6 2 0
样例输出 Sample Output
2.125
数据范围及提示 Data Size & Hint
【数据说明】
30%的数据,n<=20
100%的数据,n<=100,p,t<=10000
二分出ans
p1+p2+..pn/t1+t2+t3+...tn=ans-->p1-t1*ans+p2-t2*ans+..pn-tn*ans=0,
以p[i]-ans+t[i]作为边权,SPFA验证是否合理
1 #include <algorithm> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 6 using namespace std; 7 8 #define N 1000+15 9 int n; 10 double p[N][N],t[N][N]; 11 12 int head[N],sumedge; 13 struct Edge 14 { 15 int u,v,next; 16 double val; 17 Edge(int u=0,int v=0,int next=0,double val=0.0): 18 u(u),v(v),next(next),val(val){} 19 }edge[N*N]; 20 void ins(int u,int v,double val) 21 { 22 edge[++sumedge]=Edge(u,v,head[u],val); 23 head[u]=sumedge; 24 } 25 26 queue<int>que; 27 double dis[N]; 28 int vis[N],cnt[N]; 29 bool SPFA() 30 { 31 que.push(1); 32 vis[1]=1;dis[1]=0; 33 for(;!que.empty();) 34 { 35 int fro=que.front();que.pop();vis[fro]=0; 36 for(int i=head[fro];i;i=edge[i].next) 37 { 38 int to=edge[i].v; 39 if(dis[to]<dis[fro]+edge[i].val) 40 { 41 dis[to]=(double)dis[fro]+edge[i].val; 42 if(!vis[to]) 43 { 44 vis[to]=1; 45 que.push(to); 46 if(++cnt[to]>n) 47 return 1; 48 } 49 } 50 } 51 } 52 return dis[n]>0; 53 } 54 55 double l,r,mid,ans; 56 bool check(double x) 57 { 58 memset(dis,-0x3f3f3f3f,sizeof(dis)); 59 memset(edge,0,sizeof(edge)); 60 memset(head,0,sizeof(head)); 61 memset(vis,0,sizeof(vis)); 62 memset(cnt,0,sizeof(cnt)); 63 sumedge=0; 64 for(int u=1;u<=n;u++) 65 for(int v=1;v<=n;v++) 66 ins(u,v,(double)p[u][v]-t[u][v]*x); 67 return SPFA(); 68 } 69 70 int main() 71 { 72 scanf("%d",&n); 73 for(int i=1;i<=n;i++) 74 for(int j=1;j<=n;j++) 75 scanf("%lf",&p[i][j]); 76 for(int i=1;i<=n;i++) 77 for(int j=1;j<=n;j++) 78 scanf("%lf",&t[i][j]); 79 r=100000; 80 for(;r-l>0.0001;) 81 { 82 mid=(l+r)/2.0; 83 if(check(mid)) l=mid; 84 else r=mid; 85 } 86 printf("%.3lf",l); 87 return 0; 88 }
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。