最优比率环问题。二分答案,对于每一个mid,把节点的happy值归类到边上。
对于每条边,用mid×weight减去happy值,如果不存在负环,说明还可以更大。
1 /*--------------------------------------------------------------------------------------*/ 2 // Helica's header 3 // Second Edition 4 // 2015.11.7 5 // 6 #include <algorithm> 7 #include <iostream> 8 #include <cstring> 9 #include <ctype.h> 10 #include <cstdlib> 11 #include <cstdio> 12 #include <vector> 13 #include <string> 14 #include <queue> 15 #include <stack> 16 #include <cmath> 17 #include <set> 18 #include <map> 19 20 //debug function for a N*M array 21 #define debug_map(N,M,G) printf(" ");for(int i=0;i<(N);i++) 22 {for(int j=0;j<(M);j++){ 23 printf("%d",G[i][j]);}printf(" ");} 24 //debug function for int,float,double,etc. 25 #define debug_var(X) cout<<#X"="<<X<<endl; 26 /*--------------------------------------------------------------------------------------*/ 27 using namespace std; 28 29 const int INF = 0x3f3f3f3f; 30 const int maxn = 1e3+100; 31 const double eps = 1e-3; 32 int N,M; 33 int happy[maxn]; 34 35 struct Edge 36 { 37 int to,next,w; 38 }edge[10*maxn]; 39 40 int head[maxn],cnt[maxn],tol; 41 double dist[maxn]; 42 bool vis[maxn]; 43 44 bool SPFA(double mid) 45 { 46 memset(vis,false,sizeof(vis)); 47 memset(cnt,0,sizeof(cnt)); 48 for(int i=1;i<=N;i++)dist[i]=INF; 49 dist[1]=0; 50 queue<int>Q; 51 Q.push(1); 52 while(!Q.empty()){ 53 int u=Q.front(); 54 Q.pop(); 55 vis[u]=false; 56 cnt[u]++; 57 if(cnt[u]>N)return true; 58 for(int i=head[u];i!=-1;i=edge[i].next){ 59 int v=edge[i].to,w=edge[i].w; 60 double tmp=mid*w-happy[v]; 61 if(dist[u]+tmp<dist[v]){ 62 dist[v]=dist[u]+tmp; 63 if(!vis[v]){ vis[v]=true;Q.push(v); } 64 } 65 } 66 } 67 return false; 68 } 69 void add_edge(int u,int v,int w) 70 { 71 edge[tol].to = v; 72 edge[tol].w = w; 73 edge[tol].next = head[u]; 74 head[u] = tol++; 75 } 76 77 int main() 78 { 79 //freopen("input.in","r",stdin); 80 while(~scanf("%d%d",&N,&M)) 81 { 82 memset(head,-1,sizeof head); 83 tol = 0; 84 for(int i=1;i<=N;i++) scanf("%d",&happy[i]); 85 for(int i=0,u,v,w;i<M;i++) 86 { 87 scanf("%d%d%d",&u,&v,&w); 88 add_edge(u,v,w); 89 } 90 double L = 0,R = 10000.0,mid; 91 92 while(abs(L-R)>eps) 93 { 94 mid = (L+R)/2.0; 95 if(SPFA(mid)) L = mid; 96 else R = mid; 97 } 98 99 printf("%.2f ",mid); 100 } 101 }