Description
对于一张有向图,要你求图中最小圈的平均值最小是多少,即若一个圈经过k个节点,那么一个圈的平均值为圈上k条边权的和除以k,现要求其中的最小值
Input
第一行2个正整数,分别为n和m
以下m行,每行3个数,表示边连接的信息
以下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
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 }