POJ3621 Sightseeing Cows

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

最短路

二分答案\(mid\)

\(u \rightarrow v\)边权为\(mid*cost_{u,v}-val[u]\)

若有负环则满足题意

POJ居然不能用%.lf ,只能用%.f

\(Code:\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#define D double
#define N 100005
using namespace std;
int x,y,z,tot,n,m,head[N],nxt[N],d1[N],d2[N],in[N];
D l,r,ans,dis[N],val[N];
bool vis[N];
queue<int>q;
void add(int x,int y,int z)
{
    tot++;
    d1[tot]=y;
    d2[tot]=z;
    nxt[tot]=head[x];
    head[x]=tot;
}
bool spfa(D mid)
{
    for (int i=1;i<=n;i++)
        dis[i]=10000000000000.0,in[i]=0,vis[i]=false;
    dis[1]=0.0;
    while (!q.empty())
        q.pop();
    q.push(1);
    vis[1]=true,in[1]++;
    while (!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        for (int i=head[u];i;i=nxt[i])
        {
            int v=d1[i];
            D cost=mid*(D)d2[i]-val[v];
            if (dis[u]+cost<dis[v])
            {
                dis[v]=dis[u]+cost;
                if (!vis[v])
                {
                    vis[v]=true;
                    in[v]++;
                    if (in[v]>=n)
                        return true;
                    q.push(v);
                }
            }
        }
    }
    return false;
}
int main()
{
    while (~scanf("%d%d",&n,&m))
    {
        ans=l=r=0.0;
        for (int i=1;i<=n;i++)
            head[i]=0;
        tot=0;
        for (int i=1;i<=n;i++)
            scanf("%lf",&val[i]),r+=val[i];
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
        }
        while (r-l>1e-4)
        {
            D mid=(l+r)/2;
            if (spfa(mid))
                l=mid; else
                r=mid;
        }
        printf("%.2f\n",l);
    }
    return 0;
}
posted @ 2020-08-06 14:46  GK0328  阅读(51)  评论(0编辑  收藏  举报