#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<vector>
#define inf 0x3f3f3f
#define maxn 3000
#define maxm 10000
#define eps 1e-3
using namespace std;
//spfa判负权回路+最优比率环。
// 大于n-1退出
//假设有一个点,除了自身,所有点都可以更新它……
//入队次数超过结点数量,证明存在回路
比率环只算终点value的思想!!!
过了,但建边的神奇性还要再想一下。。。
int em;
int n;
int head[maxn];
struct node
{
int u,v,next;double w;
}edge[maxm];
void addedge(int u,int v,double w)
{
edge[em].u=u;
edge[em].v=v;
edge[em].w=w;
edge[em].next=head[u];
head[u]=em++;
}
double d[maxn];
bool vis[maxn];
int cnt[maxn];
double a[maxn];
bool spfa(int s,double ans)///是可以随意选定起点的么??
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)
d[i]=inf;
d[s]=0;
vis[s]=1;
queue<int> q;
q.push(s);
cnt[s]++;//首先注意这里的加一
while(!q.empty())
{
int x=q.front();
q.pop();
vis[x]=false;
for(int i=head[x];~i;i=edge[i].next)
{
int v=edge[i].v;
double val=edge[i].w*ans-a[x];
if(d[v]>d[x]+val)
{
d[v]=d[x]+val;
if(!vis[v])
{
cnt[v]++;在这里判断负环,到底是大于等于N,还是大于n?
if(cnt[v]>=n) return true;
vis[v]=true;
q.push(v);
}
}
}
}
return false;
}
void solve()
{
double l=0;double r=1000.0;///会不会太大了???
while(r-l>eps)
{
double mid=(l+r)*0.5;
memset(cnt,0,sizeof(cnt));
if(spfa(1,mid))
l=mid;
else
r=mid;;
// printf("%.5lf %.5lf\n",mid,build(mid));
}
printf("%.2lf\n",l);
}
int x,y;
double z;
int main()
{
int m;
// freopen("input.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF)
{
em=0;memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
scanf("%lf",&a[i]);
for(int i=1;i<=m;i++)
scanf("%d%d%lf",&x,&y,&z),addedge(x,y,z);///为什么要建有向边???????????????????????????????????????
solve();
}
}
POJ 3621 最优比率环
最新推荐文章于 2021-05-02 23:43:08 发布