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;
}