SPFA Finding the Negative Ring ---------- Sightseeing Cows

Given a directed graph with L points and P edges, each point has a weight f [i], and each edge has a weight t [i].
Find a ring in the graph so that the "sum of the weights of the points on the ring" divided by the "sum of the weights of the sides of the ring" is the largest.
This maximum value is output.
Note: The data guarantees that there is at least one ring.
Input format The
first line contains two integers L and P.
Each integer in the next L line represents f [i].
Then in line P, three integers a, b, and t [i] in each line indicate that there is an edge between points a and b, and the weight of the edge is t [i].
Output format
Output a number to indicate the result, and retain two decimal places.
Data range
2≤L≤10002≤L≤1000,

2≤P≤50002≤P≤5000,

1≤f [i], t [i] ≤10001≤f [i], t [i] ≤1000
Input sample:
5 7
30
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2

Sample output:
6.00

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010, M = 5010;
int n, m;
int wf[N];
int h[N], e[M], wl[M], ne[M], idx;
double dist[N];
int q[N], cnt[N];
bool st[N];
void add(int a, int b, int c){
 e[idx] = b, wl[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}
bool check(double mid){
 memset(dist, 0, sizeof dist);
 memset(cnt, 0, sizeof cnt);
 memset(st, 0, sizeof st);
  int hh = 0, tt = 0;
 for (int i = 1; i <= n; i ++){
  q[tt ++] = i;
  st[i] = true;
 }
  while(hh != tt){
  int t = q[hh ++];
  if (hh == N)   hh = 0;
  st[t] = false;
   for (int i = h[t]; ~i; i = ne[i]){
   int j = e[i];
   if (dist[j] < dist[t] + wf[t] - mid * wl[i]){
       dist[j] = dist[t] + wf[t] - mid * wl[i];
   cnt[j] = cnt[t] + 1;
   if (cnt[j] >= n)   return true;
   if (!st[j]){
    q[tt ++] = j;
    if (tt == N)   tt = 0;
    st[j] = true;
   }
  }
 }
 }
 return false;
}
int main(){
 cin >> n >> m;
 for (int i = 1; i <= n; i ++)   scanf("%d", &wf[i]);
  memset(h, -1, sizeof h);
 for (int j = 0; j < m; j ++){
  int a, b, c;
  cin >> a >> b >> c;
  add(a, b, c);
 }
  double l = 0, r = 1010;
 while(r - l > 1e-4){
  double mid = (l + r) / 2;
  if (check(mid))   l = mid;
  else              r = mid;
 }
  printf("%.2lf\n", l);
  return 0;
}

164 original articles published · Like 112 · Visits 6770

Guess you like

Origin blog.csdn.net/qq_45772483/article/details/105471828