codevs1183泥泞的道路
2016-05-01 14:45
281 查看
题意:给定一张有向稠密图和通过每条边的时间和路程,问从1到n的路程/时间 最大为多少
正解:SPFA+二分答案
开始做的时候,想直接跑图论,后来发现好像不对(不然数据范围怎么这么小)
但是显然要用到图论,机智的我就想到了二分答案。
考虑,假如有一个ans,那么如果存在length i / time i >=ans(i属于路径上的边),那么显然更优 ,则可发现问题可转换为如果一个答案更优,那么对于以 length i - ans*time i 为权值,重新构的图中,如果到达n的最长路不小于n,显然答案可以更优,只需要二分答案就可以了.另外如果有正权环显然是可以的
唯独要注意的是,精度要求要满足题意,显然不能只分到第三位小数就停了,那样的话会gi
正解:SPFA+二分答案
开始做的时候,想直接跑图论,后来发现好像不对(不然数据范围怎么这么小)
但是显然要用到图论,机智的我就想到了二分答案。
考虑,假如有一个ans,那么如果存在length i / time i >=ans(i属于路径上的边),那么显然更优 ,则可发现问题可转换为如果一个答案更优,那么对于以 length i - ans*time i 为权值,重新构的图中,如果到达n的最长路不小于n,显然答案可以更优,只需要二分答案就可以了.另外如果有正权环显然是可以的
唯独要注意的是,精度要求要满足题意,显然不能只分到第三位小数就停了,那样的话会gi
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<queue> #include<vector> using namespace std; const int MAXN = 101; int n; int tim[MAXN][MAXN],s[MAXN][MAXN]; long double ju[MAXN][MAXN]; double dis[MAXN]; bool vis[MAXN]; int num[MAXN];//记录经过次数,判环 long double ans; //二分答案+SPFA queue<int>q; inline int getint() { int w=0,q=0; char c=getchar(); while((c<'0' || c>'9') && c!='-') c=getchar(); if (c=='-') q=1, c=getchar(); while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; } inline bool work(long double x){//跑最长路径 for(int i=1;i<=n;i++) dis[i]=-0x7ffffff;//置为更小的负值 // memset(dis,0,sizeof(dis)); ans=x; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) ju[i][j]=s[i][j]-x*tim[i][j]; memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); while(!q.empty()) q.pop(); q.push(1); vis[1]=1; dis[1]=0; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=1;i<=n;i++) if(i!=u){ if(dis[i]<dis[u]+ju[u][i]) { dis[i]=dis[u]+ju[u][i]; if(!vis[i]) { vis[i]=1; q.push(i); num[i]++; if(num[i]>=n) return true; } } } } if(dis >=0) return true;//存在更优的答案 return false; } int main() { n=getint(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) s[i][j]=getint(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) tim[i][j]=getint(); long double l=0.00,r=10000.00; //long double jingdu=0.00001; long double jingdu=0.0001; while(r-l-jingdu>=0) { long double mid=l+(r-l)/2.0; if(work(mid)) l=mid; else r=mid; } printf("%.3lf",(double)l); return 0; }
相关文章推荐
- 20135201李辰希 《Linux内核分析》期中总结
- 关于MYSQL 和INNODB的逻辑关系图。最好的理解是一点点动手做,观察,记录,思考。
- 2016 UESTC Training for Data Structures R - Japan CDOJ 383 树状数组 逆序对
- nodejs笔记之:事件驱动,线程池,非阻塞,异常处理等
- 高级指针
- CodeForces 666B World Tour
- 2016 UESTC Training for Data Structures Q - 昊昊爱运动 II CDOJ 1259 线段树+bitset
- 配置FTP服务器——passive mode
- 数据挖掘中所需的概率论与数理统计知识
- android之MTP框架和流程分析
- ZOJ 3782
- zookeeper的工作原理
- 2016 UESTC Training for Data Structures P - 浑身难受 CDOJ 1276 树状数组
- input框光标设置为最末尾的方法
- iOS SDL2静态库的编译
- 2016 UESTC Training for Data Structures O - 卿学姐种美丽的花 CDOJ 1344 线段树/树状数组
- WPF datagrid取行数和单元格
- iOS开发踩过的坑
- 最大熵模型中的数学推导
- <LeetCode OJ> 89. Gray Code