动态规划训练之十八

Posted wzxbeliever

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划训练之十八相关的知识,希望对你有一定的参考价值。

https://www.luogu.org/problem/P2868

分析:

明显的01分数规划

求最优比率环

用dfs版的spfa找负环

二分就好

code by wzxbeliever:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 51000
using namespace std;
bool vis[N];
int n,m,x,y,z,tot;
int c[N],num[N],head[N];
double ans,mid,l,r,w[N],dis[N];
struct Edge
{
    int to,dis,from,next;
}edge[N];
int add(int x,int y,int z)
{
    tot++;
    edge[tot].to=y;
    edge[tot].dis=z;
    edge[tot].next=head[x];
    head[x]=tot;
}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int spfa(int x)
{
    vis[x]=true;
    for(int i=head[x];i;i=edge[i].next)
    {
        int t=edge[i].to;
        if(dis[t]>dis[x]+w[i])
        {
            dis[t]=dis[x]+w[i];
            if(vis[t]||spfa(t))
            {
                vis[x]=false;
                return true;
            }  
        }
    }
    vis[x]=false;
    return false;
}
int pd()
{
    for(int i=1;i<=n;i++)dis[i]=1e9;
    for(int i=1;i<=n;i++)
        if(spfa(i)) return true;
    return false;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++) c[i]=read();
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read(),z=read();
        add(x,y,z);
    }
    l=0,r=500005;
    while(r-l>1e-6)
    {
        mid=(l+r)/2;
        for(int i=1;i<=tot;i++)
        {
            int t=edge[i].to;
            w[i]=(double)mid*edge[i].dis-c[t];
        }
        if(pd())ans=mid,l=mid;
        else r=mid;
    }
    printf("%.2lf",ans);
    return 0;
}

以上是关于动态规划训练之十八的主要内容,如果未能解决你的问题,请参考以下文章

动态规划训练之十一

ACM专题

NOIP训练营动态规划内部训练题!

动态规划训练一

LeetCode动态规划训练营(1~5天)

动态规划训练之三