POJ 3621 Sightseeing Cows 最大密度环 01分数规划

最大密度环 01分数规划

首先的一个结论就是,不会存在环套环的问题,即最优的方案一定是一个单独的环,而不是大环套着小环的形式。这个的证明其实非常的简单,大家可以自己想一下(提示,将大环上的收益和记为x1,花费为y1,小环上的为x2,y2。重叠部分的花费为S。表示出来分类讨论即可)。有了这个结论,我们就可以将花费和收益都转移到边上来了,因为答案最终一定是一个环,所以我们将每一条边的收益规定为其终点的收益,这样一个环上所有的花费和收益都能够被正确的统计。

解决了蛋疼的问题之后,就是01分数规划的部分了,我们只需要计算出D数组后找找有没有正权环即可,不过这样不太好,不是我们熟悉的问题,将D数组全部取反之后,问题转换为查找有没有负权环,用spfa或是bellman_ford都可以。这道题目就是典型的不适合用Dinkelbach,记录一个负权环还是比较麻烦的,所以二分搞定。


Sightseeing Cows

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 7927   Accepted: 2673

Description

Farmer John has decided to reward his cows for their hard work by taking them on a tour of the big city! The cows must decide how best to spend their free time.

Fortunately, they have a detailed city map showing the L (2 ≤ L ≤ 1000) major landmarks (conveniently numbered 1.. L) and the P (2 ≤ P ≤ 5000) unidirectional cow paths that join them. Farmer John will drive the
cows to a starting landmark of their choice, from which they will walk along the cow paths to a series of other landmarks, ending back at their starting landmark where Farmer John will pick them up and take them back to the farm. Because space in the city
is at a premium, the cow paths are very narrow and so travel along each cow path is only allowed in one fixed direction.

While the cows may spend as much time as they like in the city, they do tend to get bored easily. Visiting each new landmark is fun, but walking between them takes time. The cows know the exact fun values Fi (1 ≤ Fi ≤
1000) for each landmark i.

The cows also know about the cowpaths. Cowpath i connects landmark L1i to L2i (in the direction L1i -> L2i ) and requires time Ti (1
≤ Ti ≤ 1000) to traverse.

In order to have the best possible day off, the cows want to maximize the average fun value per unit time of their trip. Of course, the landmarks are only fun the first time they are visited; the cows may pass through the landmark more than once, but they
do not perceive its fun value again. Furthermore, Farmer John is making the cows visit at least two landmarks, so that they get some exercise during their day off.

Help the cows find the maximum fun value per unit time that they can achieve.

Input

* Line 1: Two space-separated integers: L and P

* Lines 2..L+1: Line i+1 contains a single one integer: Fi

* Lines L+2..L+P+1: Line L+i+1 describes cow path i with three space-separated integers: L1i , L2i , and Ti

Output

* Line 1: A single number given to two decimal places (do not perform explicit rounding), the maximum possible average fun per unit time, or 0 if the cows cannot plan any trip at all in accordance with the above rules.

Sample Input

5 7
30
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2

Sample Output

6.00

Source

USACO 2007 December Gold

[Submit]   [Go Back]   [Status]  
[Discuss]

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>

using namespace std;

const int maxn=5500;
const double eps=1e-7;

int n,m;
double fun[maxn/5];

struct Edge
{
    int to,next;
    double w;
}edge[maxn*2];

int Adj[maxn/5],Size;

void init()
{
    memset(Adj,-1,sizeof(Adj));Size=0;
}

void add_edge(int u,int v,double w)
{
    edge[Size].to=v;
    edge[Size].w=w;
    edge[Size].next=Adj[u];
    Adj[u]=Size++;
}

double dist[maxn/5];
int cq[maxn/5];
bool inq[maxn/5];

bool spfa(double r)
{
    for(int i=0;i<=n+1;i++) dist[i]=1e30;
    memset(cq,0,sizeof(cq));
    memset(inq,false,sizeof(inq));

    dist[1]=0; queue<int> q;
    inq[1]=true; q.push(1); cq[1]=1;

    while(!q.empty())
    {
        int u=q.front(); q.pop();
        inq[u]=false;
        for(int i=Adj[u];~i;i=edge[i].next)
        {
            int v=edge[i].to;
            double W=edge[i].w*r-fun[v];
            if(dist[v]>dist[u]+W)
            {
                dist[v]=dist[u]+W;
                if(!inq[v])
                {
                    inq[v]=true;
                    cq[v]++;
                    if(cq[v]>=n) return true;
                    q.push(v);
                }
            }
        }
    }
    return false;
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(int i=1;i<=n;i++)
            scanf("%lf",fun+i);
        for(int i=0;i<m;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add_edge(a,b,c);
        }

        double low=0.,high=1000.,mid,ans;
        while(fabs(low-high)>eps)
        {
            mid=(low+high)/2.;
            if(spfa(mid))
            {
                ans=low=mid;
            }
            else high=mid;
        }

        printf("%.2lf\n",ans);
    }
    return 0;
}
时间: 2024-10-14 02:07:06

POJ 3621 Sightseeing Cows 最大密度环 01分数规划的相关文章

poj 3621 Sightseeing Cows 负环探测解参数搜索

题意: 有向图中每个点有一个欢乐值,边有边权,要求一条环路,使环路上欢乐值得和/路径和最大. 分析: 二分参数,判断是否存在负权,这里判负圈没用spfa,用的是一种效率很高的方法. 代码: //poj 3621 //sep9 #include <iostream> #include <cmath> using namespace std; const int maxN=1024; const int maxM=5012; int n,m,e; struct Edge { int v

poj 3621 Sightseeing Cows(最优比例生成环,01分数规划)

http://poj.org/problem?id=3621 大致题意:给出一个有向图,每个点都有一个点权,每条有向边也都有一个边权,要求出一个环使得环中点权之和与边权之和的比值最大. 思路:和最优比率生成树异曲同工.设点权是v[i],边权是e[i].不同的是这里一个是点,一个是边.怎么像生成树一样把这两个值放到一起呢?可以把他们都转化到边上.同样的二分λ,每次给边重新赋权为v[i] - λ*e[i](v[i]是该边终点的点权).因为要求比值最大,那么在这前提下于图中的所有环都<=0, 所以我们

POJ 3621 Sightseeing Cows 【01分数规划+spfa判正环】

题目链接:http://poj.org/problem?id=3621 Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11526   Accepted: 3930 Description Farmer John has decided to reward his cows for their hard work by taking them on a tour of the big ci

POJ 3621 Sightseeing Cows(最优比例环+SPFA检测)

Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10306   Accepted: 3519 Description Farmer John has decided to reward his cows for their hard work by taking them on a tour of the big city! The cows must decide how best to

Desert King (poj 2728 最优比率生成树 0-1分数规划)

Language: Default Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 22113   Accepted: 6187 Description David the Great has just become the king of a desert country. To win the respect of his people, he decided to build channels

『POJ 2976』Dropping tests (01分数规划)

题目链接 Descrip In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be . Given your test scores and a positive integer k, determine how high you can make your cumulative avera

POJ 3621 Sightseeing Cows 01分数规划,最优比例环的问题

http://www.cnblogs.com/wally/p/3228171.html 题解请戳上面 然后对于01规划的总结 1:对于一个表,求最优比例 这种就是每个点位有benefit和cost,这样就是裸的01规划 2:对于一个树,求最优比例 这种就是每条边有benefit和cost,然后通过最小生成树来判断 3:对于一个环求最优比例 这种也是每条边有benefit和cost,然后通过spfa来判断 其实01规划最核心的地方,在于构建01规划函数,构建好函数,然后根据单调性,判断大于0或者小

POJ 3621 Sightseeing Cows | 01分数规划

题目: http://poj.org/problem?id=3621 题解: 二分答案,检查有没有负环 #include<cstdio> #include<algorithm> #include<cstring> #define N 1005 using namespace std; struct node { int nxt,v; double w; }e[N*5]; int head[N],ecnt,L,P; double dis[N],fun[N],l,r,mid

POJ 3621 Sightseeing Cows [最优比率环]

感觉去年9月的自己好$naive$ http://www.cnblogs.com/candy99/p/5868948.html 现在不也是嘛 裸题,具体看学习笔记 二分答案之后判负环就行了 $dfs$版超快 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; typed