poj 3621 Sightseeing Cows

来源:互联网 发布:潍坊网络广播电视台 编辑:程序博客网 时间:2024/06/06 03:12
类型:分数规划

题目:牛可以从任意点出发, 每个点有欢乐值, 一个点可以去多次, 但是欢乐值只增加一次, 每条边有时间消耗, 求

一条回路使得 总欢乐值/总时间 最大

来源:USACO 2007 December Gold

思路:设当前答案为ans,构造新边edge(u, v) * ans - f[v]。假设存在负环,则有

edge(u1, v1) * ans - f[v1] + edge(v1, v2) * ans - f[v2] ... < 0

变形得:(edge(u, v)) / (f[v]) > ans

那么可知ans小了

二分ans,每次判断负环回路

参考:http://helanic.yo2.cn/articles/pkupoj-3621-sightseeing-cows.html

// poj 3621 - Sightseeing Cows// 272K625MS#include <iostream>#include <queue>#include <string>#include <cstdio>#include <cmath>#include <cstring>using namespace std;#define MAXN 1010#define EPS 0.0001#define INF 0x7f7f7f7fbool vis[MAXN];int L, P;int cnt[MAXN], head[MAXN];double f[MAXN];double l, r, mid;double dist[MAXN];struct edge{    int v, nxt;    double w;}e[MAXN * 5];int spfa() {    int i;    double newedge;    memset(vis, false, sizeof(vis));    memset(cnt, 0, sizeof(cnt));    for(i = 1; i <= L; ++i) dist[i] = INF;    dist[1] = 0;    queue<int> q;    q.push(1);    vis[1] = true;    ++cnt[1];    while(!q.empty()) {        int u = q.front();        q.pop();        vis[u] = false;        for(i = head[u]; i != -1; i = e[i].nxt) {            int v = e[i].v;            // !!!            newedge = e[i].w * mid - f[v];            if(newedge + dist[u] < dist[v]) {                dist[v] = newedge + dist[u];                if(!vis[v]) {                    q.push(v);                    vis[v] = true;                    if((++cnt[v]) >= L)                        return -1;                }            }        }    }    return 1;}void init() {    int i, u, v;    double w;    memset(head, -1, sizeof(head));    for(i = 1; i <= L; ++i)        scanf("%lf", &f[i]);    for(i = 0; i != P; ++i) {        scanf("%d %d %lf", &u, &v, &w);        e[i].v = v, e[i].w = w;        e[i].nxt = head[u];        head[u] = i;    }}double proc() {    l = 0.0, r = 1000.0;    while(r - l > EPS) {        mid = (l + r) / 2.0;        (spfa() < 0) ? l = mid : r = mid;    }    return mid;}int main() {    while(scanf("%d %d", &L, &P) == 2) {        init();        double x = proc();        printf("%.2lf\n", x);    }    return 0;}