码迷,mamicode.com
首页 > 其他好文 > 详细

最优比率环

时间:2017-10-03 17:48:52      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:pre   最大   nbsp   display   string   bool   gif   int   return   

POJ 3621 - Sightseeing Cows

 

找到一个圈,要求这个圈的点权和/边权和在所有的圈中最大,输出这个比率

设最大比率为ans ,∑V/∑E为一般的圈的比率k

最大的圈的k,即ans,>=所有的圈的k

即ans>=∑V/∑E

变形:∑(ans*E-V) > 0

图中边权改为ans*E-V (实际上不需要改边权,在使用时调整一下就行)(E是V的入边或者出边都可以)

二分ans,跑spfa

如果有负环 说明ans小了

没有负环 说明ans大了

最后注意控制精度在范围内

 

技术分享
#include<cstdio>
#include<cstring>//ans*e[i]-v[i]
#include<queue>
using namespace std;
const int maxn = 1007, maxm = 5007;
const double inf = 1.0 * 0x3f3f3f3f;
struct Edge{
    int v, nxt;
    double w;
    Edge(){}
    Edge(int v, double w, int nxt):v(v), w(w), nxt(nxt){}
}edge[maxm];
int n, m;
int head[maxn], cnt[maxn], inq[maxn], tmp[maxn], tot;
double d[maxn], mid;
void addedge(int u, int v, double w){
    edge[tot] = Edge(v, w, head[u]);
    head[u] = tot++;
}
bool spfa(int st){
    for(int i = 0; i < maxn; i++)
        d[i] = inf;
    memset(cnt, 0, sizeof cnt);
    memset(inq, 0, sizeof inq);
    queue<int>Q;
    inq[st] = 1;
    d[st] = 0;
    Q.push(st);
    while(!Q.empty()){
        int u = Q.front();
        Q.pop();
        inq[u] = 0;
        for(int i = head[u]; ~i; i = edge[i].nxt){
            int v = edge[i].v;
            double w = edge[i].w;
            w = mid*w-tmp[u];
            if(d[v] > d[u]+w){
                d[v] = d[u]+w;
                cnt[v] = cnt[u]+1;
                if(!inq[v]){
                    Q.push(v);
                    inq[v] = 1;
                }
                if(cnt[v] > n){
                    return false;
                }
            }
        }
    }
    return true;
}//0 -- 1e6
int main(){
    while(scanf("%d%d", &n, &m)!=EOF){
        tot = 0;
        memset(head, -1, sizeof head);
        for(int i = 1; i <= n; i++)
            scanf("%d", &tmp[i]);
        while(m--){
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            addedge(u, v, w);
        }
        double l = 0, r = 1e6, ans = 0;
        while(r-l>0.0001){
            mid = (l+r)/2;
            if(spfa(1)){
                ans = mid;
                r = mid;
            }
            else
                l = mid;
        }
        printf("%.2lf\n", ans);
    }
    return 0;
}
View Code

 

最优比率环

标签:pre   最大   nbsp   display   string   bool   gif   int   return   

原文地址:http://www.cnblogs.com/DearDongchen/p/7623984.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!