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

本文介绍了一种解决最优比率环问题的方法,通过将边的价值转换为起点或终点的价值,并使用SPFA算法判断是否存在正权环来寻找最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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

题解

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

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 1005
#define E 5005

const 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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值