zoukankan      html  css  js  c++  java
  • poj3621 Sightseeing Cows(二分+spfa)

    题目链接:http://poj.org/problem?id=3621

    题意:求一个环路,欢乐值 / 总路径最大(欢乐值是每个点权,边有边权)

    思路:ans=  val[i]/ w[i]   (假设val[i]为点权,w[i]为边权)

     ans*w[i]-val[i] = 0  当我们要找最大的ans时,且要保留精度很明显要用二分,寻找最大ans。

    哪怎么判定有环呢?  我们知道 spaf是可以判断是否有负环的。

    我们将spfa以前的边权改为   ans*w[i]-val[i]  如果有负环则说明,ans偏小了(很明显,有负环表明环内ans*w[i]-val[i]之和<0,要增大ans才能使之和等于0),否则ans偏大。

    交到G++wa了一发, 在G++环境下,对于double 类型 真正的标准是用%lf输入,用%f输出。交c++就不用,因为 对于double 类型用%lf 输入用%lf输出是window 环境下VC的标准但不是真正的标准。

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=1500; 
    const int maxm=5500;
    struct node{
        int u,v,w,nxt;
    }e[maxm];
    int head[maxn],val[maxn],num[maxn];
    bool vis[maxn];
    double d[maxn];
    int n,m,cnt=0;
    
    void add(int u,int v,int w)
    {
        e[cnt].u=u;
        e[cnt].v=v;
        e[cnt].w=w;
        e[cnt].nxt=head[u];
        head[u]=cnt++;
    }
    
    bool spfa(double x)
    {
        memset(vis,0,sizeof(vis));
        memset(num,0,sizeof(num));
        queue<int> q;
        for(int i=1;i<=n;i++)
            d[i]=inf;
        d[1]=0;
        vis[1]=1;
        q.push(1);
        num[1]=1;
        while(!q.empty())
        {
            int u=q.front();q.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=e[i].nxt)
            {
                int v=e[i].v;
                int w=e[i].w;
                double sum=-val[u]+x*w;
                if(d[v]>d[u]+sum)
                {
                    d[v]=d[u]+sum;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        q.push(v);
                        num[v]++;
                        if(num[v]>n)
                            return true;
                    }
                }
            }
        }
        return false;
    }
    
    int main()
    {
        cnt=0;
        int u,v,w;
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&val[i]);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        double l=0,r=10000,mid;
        while(r-l>0.001)
        {
            mid=(r+l)/2;
            if(spfa(mid))
                l=mid;
            else
                r=mid;
        }
        printf("%.2lf
    ",l);
        return 0;
    }
  • 相关阅读:
    ArcGIS Engine 中的多线程使用
    Arcgis栅格时序地图制作---时间轴动态展示多期影像
    R树空间索引
    R-Tree空间索引算法的研究历程和最新进展分析
    学生表、课程表、 成绩表 、教师表sql练习
    Mysql建表出现1005错误
    MySQL数据类型详解
    数据库操作语句类型(DQL、DML、DDL、DCL)简介
    Spring MVC标签<mvc: annotation-driven />小结 原
    EasyUI Menu 菜单
  • 原文地址:https://www.cnblogs.com/xiongtao/p/11216731.html
Copyright © 2011-2022 走看看