Description

对于一张有向图,要你求图中最小圈的平均值最小是多少,即若一个圈经过k个节点,那么一个圈的平均值为圈上k条边权的和除以k,现要求其中的最小值

Input

第一行2个正整数,分别为n和m
   以下m行,每行3个数,表示边连接的信息

Output

一行一个数,表示最小圈的值。你的答案被视为正确当且仅当与标准答案的绝对误差不超过1e-5

Sample Input

输入1:
4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
输入2:
2 2
1 2 -2.9
2 1 -3.1

Sample Output

输出1:
3.666667
输出2:
-3.000000

Data Constraint

20%:n<=100,m<=1000
60%:  n<=1000 m<=5000
100%:  n<=3000 m<=10000
       abs(Wi,j)<=10^5
 
做法:分数规划,将求值问题变成可行性判断问题。 然后要利用深搜版的 SPFA/或者 dfs,用于判负环,来求可行性,如果是宽搜版的会被卡 T。
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define rep(i,a,b) for(int i=a;i<=b;i++)
 5 #define fx(i,x) for(int i=ls[x];i;i=e[i].next)
 6 #define fill(i,x) memset(i,x,sizeof(i))
 7 #define M 10007
 8 using namespace std;
 9 const double eps=1e-10;
10 double l=-M*10,r=M*10,mid;
11 double d[M];
12 int n,m,ls[M],tot;
13 struct edge{
14     int to,next;
15     double w;
16 }e[M];
17 bool judge,flag[M];
18 
19 inline void Add(int x,int y,double z){
20     e[++tot].to=y;
21     e[tot].next=ls[x];
22     e[tot].w=z;
23     ls[x]=tot;
24 }
25 
26 inline void Spfa(int x){
27     flag[x]=1;
28     fx(i,x){
29         int v=e[i].to;
30         if(d[x]+e[i].w-mid<d[v]){
31             if(flag[v]){
32                 judge=1;
33                 return;
34             }
35             d[v]=d[x]+e[i].w-mid;
36             Spfa(v);
37             if(judge) return;
38         }
39     }
40     flag[x]=0;
41 }
42 
43 inline bool Calc(){
44     fill(d,0);
45     fill(flag,0);
46     judge=0;
47     rep(i,1,n){
48         Spfa(i);
49         if (judge) return 0;
50     }
51     return 1;
52 } 
53 
54 void Work(){
55     for(;l+eps<r;){
56         mid=(l+r)/2;
57         if (Calc())    l=mid; else r=mid;
58     }
59     printf("%.6lf",l);
60 }
61 
62 void Init(){
63     scanf("%d%d",&n,&m);
64     rep(i,1,m){
65         int u,v;
66         double w;
67         scanf("%d%d%lf",&u,&v,&w);
68         Add(u,v,w);
69     }
70 }
71 
72 int main(){
73     Init();
74     Work();
75 }
View Code