BZOJ 3597 [Scoi2014]方伯伯运椰子

时间:2022-12-16 13:40:49

01分数规划+判负环

看到分数就直接上分数规划嘛……瞎推一下式子就行了。不知道什么是分数规划就去看胡学长论文啦。

一不小心忘记睡觉了。好困啊,把from打成flow差点没看出来……感觉身体被掏空,明天早上还有训练,赶快睡觉,就不写具体的题解了。

滚去睡觉2333

#include<cstdio> 
#include<cstring>
#define N 10005
using namespace std;
namespace runzhe2000
{
    int n, m, last[N], ecnt, inq[N]; double dis[N];
    struct pdge{int from, to, a, b, flow, cost;}pe[N];
    struct edge{int next, to; double val;}e[N<<1];
    void addedge(int a, int b, double c)
    {
        e[++ecnt] = (edge){last[a], b, c};
        last[a] = ecnt;
    }
    bool dfs(int x)
    {
        inq[x] = 1;
        for(int i = last[x]; i; i = e[i].next)
        {
            int y = e[i].to;
            if(dis[x] + e[i].val < dis[y])
            {
                dis[y] = dis[x] + e[i].val;
                if(inq[y] || dfs(y)) return 1;
            }
        }
        inq[x] = 0; return 0;
    }
    bool check(double lim)
    {
        memset(last,0,sizeof(last)); ecnt=0;
        for(int i = 1; i < m; i++)
        {
            addedge(pe[i].from,pe[i].to,pe[i].b+pe[i].cost+lim);
            if(pe[i].flow)addedge(pe[i].to,pe[i].from,pe[i].a-pe[i].cost+lim);
        }
        for(int i = 1; i <= n; i++) dis[i] = 0, inq[i] = 0;
        for(int i = 1; i <= n; i++) if(dfs(i)) return 1;
        return 0;
    }
    void main()
    {
        scanf("%d%d",&n,&m); n += 2;
        for(int i = 1; i <= m; i++)
            scanf("%d%d%d%d%d%d",&pe[i].from,&pe[i].to,&pe[i].a,&pe[i].b,&pe[i].flow,&pe[i].cost);
        double l = 0, r = 1e9;
        for(; r - l > 1e-3; )
        {
            double mid = (l+r)/2;
            if(check(mid)) l = mid;
            else r = mid;
        }
        printf("%.2lf\n",(l+r)/2);
    }
}
int main()
{
    runzhe2000::main();
}