题目描述
“那是一条神奇的天路诶~,把第一个神犇送上天堂~”,XDM先生唱着这首“亲切”的歌曲,一道猥琐题目的灵感在脑中出现了。
和C_SUNSHINE大神商量后,这道猥琐的题目终于出现在本次试题上了,旨在难到一帮大脑不够灵活的OIer们(JOHNKRAM真的不是说你……)。
言归正传,小X的梦中,他在西藏开了一家大型旅游公司,现在,他要为西藏的各个景点设计一组铁路线。但是,小X发现,来旅游的游客都很挑剔,他们乘火车在各个景点间游览,景点的趣味当然是不用说啦,关键是路上。试想,若是乘火车一圈转悠,却发现回到了游玩过的某个景点,花了一大堆钱却在路上看不到好的风景,那是有多么的恼火啊。
所以,小X为所有的路径定义了两个值,Vi和Pi,分别表示火车线路的风景趣味度和乘坐一次的价格。现在小X想知道,乘客从任意一个景点开始坐火车走过的一条回路上所有的V之和与P之和的比值的最大值。以便为顾客们推荐一条环绕旅游路线(路线不一定包含所有的景点,但是不可以存在重复的火车路线)。
于是,小X梦醒之后找到了你……
输入输出格式
输入格式:
第一行两个正整数N,M,表示有N个景点,M条火车路线,火车路线是单向的。
以下M行,每行4个正整数,分别表示一条路线的起点,终点,V值和P值。
注意,两个顶点间可能有多条轨道,但一次只能走其中的一条。
输出格式:
一个实数,表示一条回路上最大的比值,保留1位小数。
若没有回路,输出-1。
输入输出样例
5 6
1 2 1 1
4 1 6 2
5 4 8 1
2 3 2 2
5 2 4 1
3 5 6 4
2.3
说明
对于30%的数据,1≤N≤100,1≤M≤20;
对于60%的数据,1≤N≤3,000,1≤M≤2,000;
对于100%的数据,1≤N≤7,000,1≤M≤20,000,1≤Vi,Pi≤1,000.
保证答案在200以内.
思路:二分+spfa判环。
错因:不明原因的TLE。
80分代码。
#include<deque> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 50010 using namespace std; int n,m,tot; double l,r,mid; double intrest[MAXN],cap[MAXN],dis[MAXN]; int to[MAXN],head[MAXN],net[MAXN],vis[MAXN],num[MAXN]; inline int read(){ char ch=getchar();int data=0; while(ch<'0'||ch>'9') ch=getchar(); do{ data=data*10+ch-'0'; ch=getchar(); }while(ch>='0' && ch<='9'); return data; } inline void add(int u,int v,double w,double p){ to[++tot]=v;net[tot]=head[u];intrest[tot]=w;cap[tot]=p;head[u]=tot; } inline bool spfa(int s){ deque<int>que; memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); memset(dis,0x7f,sizeof(dis)); que.push_back(s); dis[s]=0;vis[s]=1;num[s]++; while(!que.empty()){ int now=que.front(); que.pop_front(); vis[now]=0; for(int i=head[now];i;i=net[i]) if(dis[to[i]]>dis[now]+mid*cap[i]-intrest[i]){ dis[to[i]]=dis[now]+mid*cap[i]-intrest[i]; if(!vis[to[i]]){ if(dis[to[i]]>dis[now]) que.push_back(to[i]); else que.push_front(to[i]); vis[to[i]]=1; num[to[i]]++; if(num[to[i]]>n) return true; } } } return false; } inline bool check(double x){ if(spfa(0)) return true; else return false; } int main(){ n=read();m=read(); for(int i=1;i<=m;i++){ int x,y;double v,p; x=read();y=read(); scanf("%lf%lf",&v,&p); add(x,y,v,p); } for(int i=1;i<=n;i++) add(0,i,0,0); l=0;r=500; while(r-l>0.01){ mid=(l+r)/2; if(check(mid)) l=mid; else r=mid; } if(l==0) cout<<"-1"; else printf("%.1lf",r); }