zoukankan      html  css  js  c++  java
  • 最优比率环

    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
    ", ans);
        }
        return 0;
    }
    View Code
    搞图论是没有用的,转行做数学题了hh
  • 相关阅读:
    jq判断鼠标滚轴向上滚动还是向下滚动
    Directory 中user Var 如何添加到通道变量中?
    Centos 6.5 freeswitch 编译mod_shout
    golang esl api
    opensips redis配置记录
    luasocket 安装记录 (FS1.4)
    luasocket 安装记录 (FS1.6)
    Callcenter 模块解析
    OpenSIPS 1.11.1安装记录
    阿里服务器挂载数据盘
  • 原文地址:https://www.cnblogs.com/DearDongchen/p/7623984.html
Copyright © 2011-2022 走看看