zoukankan      html  css  js  c++  java
  • POJ3621:Sightseeing Cows——题解

    http://poj.org/problem?id=3621

    全文翻译参自洛谷:https://www.luogu.org/problemnew/show/P2868

    题目大意:一个有向图,每个点都有一个价值,每条路通过需要一定时间,求出一个回路使得价值和/时间和最大。(重复经过一个点不会额外增加价值)

    按照01分数规划的套路,我们显然可以将路的边权更改为时间*枚举的答案-目的地价值,然后找一个环。

    如果这个环是一个负环,那么显然答案还可以变得更大,反之则需要变小。

    所以我们需要用spfa判断图中的负环。但是bfs-spfa显然太慢,所以我们需要更高效的算法——dfs-spfa,需要优化的地方。

    1.由于我们的目的不是为了求最短路,所以大可以不必将dis全部清成inf(其实连清空都不需要,可以感性理解)。

    2.dfs-spfa的好处在于一直搜,直到搜到我们找到的点已经被找过为止。

    3.剩下的就是spfa的基本操作了——当dis被更新的时候才能走这个点。

    (double和int傻傻搞不清楚……)

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<cctype>
    #include<algorithm>
    using namespace std;
    typedef double dl;
    const dl eps=1e-7;
    const int INF=2147483647;
    const int M=5001;
    const int N=1001;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct node{
        int to,nxt,l;
    }e[M];
    int head[N],f[N],cnt,n,m;
    bool vis[N];
    dl dis[N],w[M];
    inline void add(int u,int v,int l){
        cnt++;
        e[cnt].to=v;
        e[cnt].l=l;
        e[cnt].nxt=head[u];
        head[u]=cnt;
        return;
    }
    bool spfa(int u){
        vis[u]=1;
        for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(dis[v]>dis[u]+w[i]){
            dis[v]=dis[u]+w[i];
            if(vis[v]||spfa(v)){
            vis[v]=0;
            return 1;
            }
        }
        }
        vis[u]=0;
        return 0;
    }
    bool pan(){
        for(int i=1;i<=n;i++){
        if(spfa(i))return 1;
        }
        return 0;
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=n;i++)f[i]=read();
        for(int i=1;i<=m;i++){
        int u=read(),v=read(),l=read();
        add(u,v,l);
        }
        dl l=0,r=100000;
        while(r-l>eps){
        dl mid=(l+r)/2;
        for(int i=1;i<=cnt;i++){
            int v=e[i].to;
            w[i]=(dl)mid*e[i].l-f[v];
        }
        if(pan())l=mid;
        else r=mid;
        }
        printf("%.2f
    ",l);
        return 0;
    }
  • 相关阅读:
    4.graph.h
    3.俄罗斯方块项目
    3.栈的实现
    26.多线程
    25.Detours劫持技术
    codeforces 616E Sum of Remainders (数论,找规律)
    poj2387 Til the Cows Come Home 最短路径dijkstra算法
    poj1274 The Perfect Stall (二分最大匹配)
    poj1459 Power Network (多源多汇最大流)
    Oracle RAC/Clusterware 多种心跳heartbeat机制介绍 RAC超时机制分析
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8268187.html
Copyright © 2011-2022 走看看