1486: [HNOI2009]最小圈
Submit: 3129 Solved: 1543
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
Sample Output
3.66666667
二分法+spfa_dfs最小圈
可以经过计算在T=60次循环后,答案精度会在小数点后8位
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 using namespace std; 6 7 const int MAXN=10005; 8 struct Edge 9 { 10 int to,next; 11 double w; 12 }E[MAXN]; 13 int node,head[MAXN]; 14 double dist[MAXN]; 15 bool flag,vis[MAXN]; 16 int n,m; 17 double mid; 18 19 void insert(int u,int v,double w) 20 { 21 E[++node]=(Edge){v,head[u],w};head[u]=node; 22 } 23 24 void spfa_dfs(int s) 25 { 26 vis[s]=1; 27 for(int i=head[s];i;i=E[i].next) 28 { 29 if(dist[E[i].to]>dist[s]+E[i].w-mid) 30 { 31 if(vis[E[i].to]){flag=1;return;} 32 else 33 { 34 dist[E[i].to]=dist[s]+E[i].w-mid; 35 spfa_dfs(E[i].to); 36 } 37 } 38 } 39 vis[s]=0; 40 } 41 42 bool check() 43 { 44 flag=0; 45 memset(dist,0,sizeof(dist)); 46 memset(vis,0,sizeof(vis)); 47 for(int i=1;i<=n;i++) 48 { 49 dist[i]=0; 50 spfa_dfs(i); 51 if(flag) return 1; 52 } 53 return 0; 54 } 55 56 int main() 57 { 58 scanf("%d%d",&n,&m); 59 for(int i=1;i<=m;i++) 60 { 61 int u,v,w; 62 scanf("%d%d%d",&u,&v,&w); 63 insert(u,v,w); 64 } 65 double l=-1e7,r=1e7; 66 int T=60; 67 while(T--) 68 { 69 mid=(l+r)/2; 70 if(check()) r=mid; 71 else l=mid; 72 } 73 printf("%.8lf",r); 74 return 0; 75 }