zoukankan      html  css  js  c++  java
  • P2868 [USACO07DEC]Sightseeing Cows G 题解

    我被裸题吊打。

    首先这题有一个比较奇怪的性质:奶牛的最优路径一定是简单环。具体证明洛谷上有。然后就成了最优比率环问题,二分答案判断负环即可。

    但是负环到底怎么判呢?跑\(n\)遍spfa?我去翻题解,发现只要把\(n\)个点同时入队,只需要跑一遍spfa就可以了。很多人写的神仙优化?

    当然判正环也是可以的。

    此题解最大意义在于复习spfa。

    代码:

    #include<cstdio>
    #include<cctype>
    #include<cstdlib>
    #include<cstring>
    #include<climits>
    #include<ctime>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<queue>
    using namespace std;
    typedef pair<int,int> pii;
    #define forg(i,x) for(int i=first[x];i;i=nxt[i])
    #define uu unsigned
    #define fi first
    #define se second
    #define ran() ((unsigned)rand())
    #define lam(z,k) [&](const z &a,const z &b){ return k; }
    #define od(x) ((x)&1)
    #define ev(x) (od(x)^1)
    #define scanf a1234=scanf
    int a1234;
    
    int n,m;const int mxn=1003,mxm=5003;
    int a[mxn],t[mxm];
    double w[mxm];
    int to[mxm],nxt[mxm],first[mxn],tot=0;
    inline void gadd(int x,int y,int tt){
        to[++tot]=y,nxt[tot]=first[x],first[x]=tot,t[tot]=tt;
    }
    bool vis[mxn];
    inline bool hdfs(int x){
        vis[x]=1;
        forg(i,x)if(vis[to[i]])return 1;else if(hdfs(to[i]))return 1;
        return 0;
    }
    
    bool inq[mxn];int cnt[mxn];
    double dis[mxn];
    queue<int>q;
    inline bool spfa(double d){
        for(int i=1;i<=n;++i)forg(j,i)w[j]=d*t[j]-a[i];//点权下放
        q=queue<int>();
        for(int i=1;i<=n;++i)q.push(i),dis[i]=0,cnt[i]=0,inq[i]=1;
        while(q.size()){
            int x=q.front();q.pop();
            inq[x]=0;
            forg(i,x)if(dis[x]+w[i]<dis[to[i]]){
                dis[to[i]]=dis[x]+w[i],cnt[to[i]]=cnt[x]+1;
                if(cnt[to[i]]>=n)return 1;
                if(!inq[to[i]])q.push(to[i]),inq[to[i]]=1;
            }
        }
        return 0;
    }
    
    int main(){
        scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)scanf("%d",a+i);for(int i=1,u,v,tt;i<=m;++i){scanf("%d%d%d",&u,&v,&tt);if(u!=v)gadd(u,v,tt);}
        bool tg=0;
        for(int i=1;i<=n;++i){memset(vis,0,sizeof(vis));if(hdfs(i))tg=1;}
        if(!tg)return puts("0"),0;
        double l=1e-3,r=1e3,mid;
        while(r-l>1e-4){
            mid=(l+r)/2;
            if(spfa(mid))l=mid;else r=mid;
        }
        printf("%.2f\n",l);
        return 0;
    }
    
    
  • 相关阅读:
    第二节:简单工厂模式(静态工厂模式)
    第一节:不使用设计模式的传统方式
    第三章:设计模式概述
    第二节:类与类之间的关系
    高斯混合模型(GMM)
    随机森林
    LDA主题模型
    Adaboost算法
    线性代数
    k-means聚类
  • 原文地址:https://www.cnblogs.com/happyguy/p/13457089.html
Copyright © 2011-2022 走看看