首页 > 学院 > 开发设计 > 正文

[POJ3621]Sightseeing Cows(01分数规划)

2019-11-08 19:44:01
字体:
来源:转载
供稿:网友

题目描述

传送门 题意:一张图,每一个点有价值,每一条边有花费,求一条起点终点相同的路径,满足价值/花费最小。其中点重复经过价值不变,边重复经过代价累加。

题解

一定不会重复走边对吧…所以是一个最优比率环问题 将边的价值看成是起点或终点的价值,二分R之后,对每一条边计算di=ai−R∗bi 然后用spfa判断是否有正权环就行了,如果有的话一定存在更优解

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 1005#define E 5005const double eps=1e-6;int n,m,x,y;int tot,point[N],nxt[E],v[E];double c[E];double val[N],e[E],ans;double dis[N];int cnt[N];bool vis[N];int q[N];void add(int x,int y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}bool spfa(){ memset(dis,0,sizeof(dis)); memset(vis,0,sizeof(vis));; memset(cnt,0,sizeof(cnt)); int head=0,tail=0; for (int i=1;i<=n;++i) { vis[i]=1;++cnt[i]; q[(++tail)%n]=i; } while (head!=tail) { int now=q[(++head)%n]; vis[now]=0; for (int i=point[now];i;i=nxt[i]) if (dis[v[i]]<dis[now]+c[i]) { dis[v[i]]=dis[now]+c[i]; if (!vis[v[i]]) { vis[v[i]]=1; ++cnt[v[i]]; if (cnt[v[i]]>n) return true; q[(++tail)%n]=v[i]; } } } return false;}bool check(double L){ for (int i=1;i<=tot;++i) c[i]=val[v[i]]-L*e[i]; return spfa();}double find(){ double l=0.0,r=1e4,mid,ans=0.0; while (r-l>eps) { mid=(l+r)/2.0; if (check(mid)) ans=l=mid; else r=mid; } return ans;}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%lf",&val[i]); for (int i=1;i<=m;++i) { scanf("%d%d%lf",&x,&y,&e[i]); add(x,y); } ans=find(); PRintf("%.2lf/n",ans);}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表