P1768 天路
题意:
小X为所有的路径定义了两个值,Vi和Pi,分别表示火车线路的风景趣味度和乘坐一次的价格。现在小X想知道,乘客从任意一个景点开始坐火车走过的一条回路上所有的V之和与P之和的比值的最大值。以便为顾客们推荐一条环绕旅游路线(路线不一定包含所有的景点,但是不可以存在重复的火车路线)。
题解:
01分数规划+spfa判负环
spfa判断负环要用DFS,因为BFS版本会超时
因为图不一定了连通,所以最好每个点都跑一遍
代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
#define N 10005
#define db double
const double inf=201*1.0;
#define M 500005
const double eps=1e-4;
db d[N];
bool vis[N];
int f[N],num[N],top=1,head[N];
int n,m,s,cnt=1;
struct Node{int v;db val,dis;int next;
}node[200100];
inline void add(int u,int v,db dis,db val)
{node[++top].v=v;node[top].val=val;node[top].dis=dis;node[top].next=head[u];head[u]=top;
}
bool spfa(db mid,int u)//dfs-spfa判环
{vis[u]=1;for(int i=head[u];i;i=node[i].next){int k=node[i].v;db val=node[i].val;double dis=node[i].dis;if(d[k]>d[u]+mid*val-dis){d[k]=d[u]+mid*val-dis;if(vis[k]||spfa(mid,k)) return true;}}vis[u]=0;return false;
}
bool check(db mid) //判断答案是否合理
{for(int i=1;i<=n;i++){d[i]=1e9;vis[i]=false;}for(int i=1;i<=n;i++){if(spfa(mid,i)==true) return true;}return false;
}
int main()
{cin>>n>>m; for(int i=1;i<=m;i++) //按题意建图{ int u,r;db p,k;scanf("%d%d%lf%lf",&u,&r,&p,&k);add(u,r,p,k);}db l=0,r=inf;while(r-l>eps)//二分答案,eps为取精度 {db mid=(l+r)/2;if(check(mid)==true) l=mid;else r=mid;}if(!l) puts("-1");else printf("%.1lf",l); return 0;
}