This question is a standard 01 score plan:
But there are some details that can be optimized:
It is not difficult to think of dividing a mid into two and then determine whether there is a ring S on the graph, whether the ring satisfies ∑i=1t(Fun[vi]−mid∗Tim[ei])>0
But the above algorithm is not easy to implement, so you can multiply both sides by -1 at the same time, so that the formula becomes ∑ i = 1 t ( m i d ∗ T i m [ e i ] − F u n [ v i ] ) < 0
Then the problem is transformed into running SPFA in each graph to find whether there is a negative cycle, if there is, l=mid, otherwise r=mid;
#include <bits/stdc++.h> #define inc(a,b,c) for(register int i=a;i<=b;i+=c) #define ini 20010 using namespace std; int n,m; struct littlestar{ int from; int to; int nxt; double w; }star[this],star2[this]; int head[ini],cnt,head2[ini]; void add(int u,int v,int w) { star[++cnt].to=v; star[cnt].nxt=head[u]; star[cnt].from=u; star[cnt].w=w; head[u]=cnt; } int c[this]; queue<int> q; double dis[ini]; int vis[ini]; int SPFA() { int tot=0; for(int i=1;i<=n;i++){ q.push(i); dis [i] = 0 ; show [i] = 1 ; } while(q.size()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=head2[u];i;i=star2[i].nxt){ int v=star2[i].to; if(dis[v]>dis[u]+star2[i].w){ dis[v]=dis[u]+star2[i].w; if(vis[v]==0){ force[v] = 1 ; q.push(v); ++tot; if(tot>2*(n+m)) return 0; } } } } return 1; } int check(double x) { inc(1,cnt,1){ star2[i]=star[i]; star2[i].w=(double)star[i].w*(double)x-(double)c[star[i].from]; } inc(1,n,1){ head2[i]=head[i]; } if(SPFA()){ return 0; } else{ return 1; } } int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } intmain () { n=read(); m=read(); inc(1,n,1) c[i]=read(); inc(1,m,1){ int u,v,w; u=read();v=read();w=read(); add(u,v,w); } double l=0.00,r=1000010.000,mid; while(r-l>1e-4){ mid=(l+r)/2; if(check(mid)){ l=mid; } else{ r=mid; } } printf("%.2lf",l); }
Reprinted in: https://www.cnblogs.com/kamimxr/p/11545032.html