<二分答案+spfa验证>codevs 1183 泥泞的道路
2017-10-14 10:59
393 查看
去题面的传送门
求一条路径(s1+s2+s3+…+sn)/(t1+t2+t3+…+tn)最小
可知对于这条路径(s1+s2+s3+…+sn)/(t1+t2+t3+…+tn)=v(平均速度)
等式变形:(s1-v*t1)+(s2-v*t2)+(s3-v*t3)+…..+(sn-v*tn)=0
问题转化为:找一个最大的v使得该等式对于某一条路径成立。
将边权转化为si-v*ti,跑最长路。二分答案,若找到终点的dis值>0,说明最长路的s偏大,也就是v偏小,这时找右区间。若终点的dis值<0,说明v太大,即使是最长的路也不能够达到要求,这时找左区间。
注意:
1.精度问题,题目要求保留3位小数,二分时,精度多一位,确保答案正确(也就是说,二分边界是r-l>=0.0001)
2.在Windows和Linux下评测时,浮点数double有误差。第一次交因为误差全wa。后来把读入的路的长度和时间变成int型,尽量减少误差才过。(原因应该是这样,因为本地输出正确,交到评测机上就wa,有一组数据Windows输出6.33,是正确的,交上之后显示输出了0.00,后来把两个变量都改成int后就过了。。。)
代码:
求一条路径(s1+s2+s3+…+sn)/(t1+t2+t3+…+tn)最小
可知对于这条路径(s1+s2+s3+…+sn)/(t1+t2+t3+…+tn)=v(平均速度)
等式变形:(s1-v*t1)+(s2-v*t2)+(s3-v*t3)+…..+(sn-v*tn)=0
问题转化为:找一个最大的v使得该等式对于某一条路径成立。
将边权转化为si-v*ti,跑最长路。二分答案,若找到终点的dis值>0,说明最长路的s偏大,也就是v偏小,这时找右区间。若终点的dis值<0,说明v太大,即使是最长的路也不能够达到要求,这时找左区间。
注意:
1.精度问题,题目要求保留3位小数,二分时,精度多一位,确保答案正确(也就是说,二分边界是r-l>=0.0001)
2.在Windows和Linux下评测时,浮点数double有误差。第一次交因为误差全wa。后来把读入的路的长度和时间变成int型,尽量减少误差才过。(原因应该是这样,因为本地输出正确,交到评测机上就wa,有一组数据Windows输出6.33,是正确的,交上之后显示输出了0.00,后来把两个变量都改成int后就过了。。。)
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; queue<int>q; int n,cnt; int fist[110],nxt[10010],tot[110]; double path[110][110],dis[110]; bool vis[110]; struct hh { int f,t,T,P; }e[10010]; void init() { memset(dis,-63,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(tot,0,sizeof(tot)); while(!q.empty()) q.pop(); q.push(1); vis[1]=1; dis[1]=0; tot[1]=1; } bool spfa(double V) { init(); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i=fist[u];i!=-1;i=nxt[i]) { int v=e[i].t; if(dis[v]<dis[u]+e[i].P-V*e[i].T) { dis[v]=dis[u]+e[i].P-V*e[i].T; if(!vis[v]) { vis[v]=true; q.push(v); tot[v]++; } } if(tot[v]>=n+3) return true; } } if(dis >=0) return true; return false; } void build(int f,int t,int T,int P) { e[++cnt]=(hh){f,t,T,P}; nxt[cnt]=fist[f]; fist[f]=cnt; } int main() { memset(fist,-1,sizeof(fist)); scanf("%d",&n); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) cin>>path[i][j]; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { int x; cin>>x; if(i!=j) build(i,j,x,path[i][j]); } double l=0,r=1e5+100; while(r-l>=0.0001)// { double mid=(l+r)/2; if(spfa(mid)) l=mid; else r=mid; } if(spfa(r)) printf("%.3lf",r); else printf("%.3lf",l); return 0; }
相关文章推荐
- codevs 1183 泥泞的道路(二分答案+spfa验证)
- CodeVS1183 泥泞的道路 解题报告【二分答案+SPFA最长路】
- codevs 1183 泥泞的道路 图论,spfa判环,二分答案
- codevs 1183 泥泞的道路(spfa+二分答案)
- CodeVS1183 泥泞的道路 题解 【二分答案】【SPFA】
- codevs 1183 泥泞的道路 二分+SPFA最长路
- [WIKIOI1183]泥泞的道路[二分答案+SPFA]
- [codevs1183]泥泞的道路(二分+正环)
- Codevs 1183 泥泞的道路
- [codevs 1183][泥泞的道路(二分+spfa)
- CODE[VS] 2744 养鱼喂妹纸 (二分答案验证 + 贪心)
- 泥泞的道路(codevs 1183)
- 【分数规划总结】周测图论1 环 & CODEVS 1183 泥泞的道路
- codevs1183 泥泞的道路
- <考试题> codevs 5440 运输计划 (二分+lca+dfs序+树上差分)
- codevs1183 泥泞的道路(最短路)
- codevs1183 泥泞的道路
- Codevs1183 泥泞的道路
- 【Codevs1183】泥泞的道路
- 【CodeVS1183】泥泞的道路