zoukankan      html  css  js  c++  java
  • POJ 3621 Sightseeing Cows

    POJ_3621

        首先,符合要求的环一定是一个简单环,不妨假设最优路线是由两个简单环x、y组成。如果x的平均值和y的平均值一样,那么选择x或y中任意一个简单环都是满足要求的,如果x的平均值和y的平均值不一样,那么加权之后一定比较大者要小,因此一定会挑那个平均值较大的简单环作为最优解。因此最终最优路线一定是简单环。

        接着就可以像求解最优比率生成树那样用0-1分数规划求解了,需要注意为了能够转化成求最短路、判负圈去解,那么0-1分数规划的表达式最终一定要变形成求某个表达式最小值的形式,这样每次二分的时候再依据这个表达式重新对边权赋值后求判负圈即可。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 1010
    #define MAXM 5010
    #define INF 0x3f3f3f3f
    int N, M, first[MAXD], e, next[MAXM], u[MAXM], v[MAXM], w[MAXM], value[MAXD], vis[MAXD];
    double dis[MAXD], f[MAXM];
    void add(int x, int y, int z)
    {
        u[e] = x, v[e] = y, w[e] = z;
        next[e] = first[x], first[x] = e ++;
    }
    void init()
    {
        int i, x, y, z;
        for(i = 1; i <= N; i ++)
            scanf("%d", &value[i]);
        memset(first, -1, sizeof(first));
        e = 0;
        for(i = 0; i < M; i ++)
        {
            scanf("%d%d%d", &x, &y, &z);
            add(x, y, z);
        }
    }
    int DFS(int cur)
    {
        int i;
        vis[cur] = 1;
        for(i = first[cur]; i != -1; i = next[i])
        {
            if(!vis[v[i]] && DFS(v[i]))
                return 1;
            else if(v[i] == 1)
                return 1;
        }
        return 0;
    }
    int negcircle()
    {
        int i, j, flag;
        double t;
        memset(dis, 0, sizeof(dis));
        for(i = 0; i < N; i ++)
        {
            flag = 0;
            for(j = 0; j < e; j ++)
                if((t = dis[u[j]] + f[j]) < dis[v[j]])
                    dis[v[j]] = t, flag = 1;
            if(!flag)
                break;
        }
        return i == N;
    }
    void solve()
    {
        int i;
        double max, min, mid;
        memset(vis, 0, sizeof(vis));
        if(!DFS(1))
        {
            printf("0\n");
            return ;
        }
        max = 1010, min = 0;
        while(min + 1e-8 < max)
        {
            mid = (max + min) / 2;
            for(i = 0; i < e; i ++)
                f[i] = mid * w[i] - value[u[i]];
            if(negcircle())
                min = mid;
            else
                max = mid;
        }
        printf("%.2f\n", mid);
    }
    int main()
    {
        while(scanf("%d%d", &N, &M) == 2)
        {
            init();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    如何使用 IDEA 向 Github 上推送和拉取代码
    CST时间和GMT时间注意事项
    CST时间GMT时间转换
    MultipartFile转InputStream
    Java中InputStream和String之间的转化
    Fastjson 之 Json 对象、Json 字符串、Java 对象之间的转换
    Git 撤销修改
    Springboot 配置文件之 Yaml
    IDEA 快速搭建一个 Springboot 应用
    ZooKeeper 安装
  • 原文地址:https://www.cnblogs.com/staginner/p/2513715.html
Copyright © 2011-2022 走看看