1486: [HNOI2009]最小圈

Time Limit: 10 Sec  Memory Limit: 64 MB
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

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 }

 

posted @ 2019-04-11 15:50  InWILL  阅读(156)  评论(0编辑  收藏  举报