码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ1486 [HNOI2009]最小圈

时间:2014-12-31 23:58:29      阅读:447      评论:0      收藏:0      [点我收藏+]

标签:

今年的最后一篇了呢。。。好伤感的说,2014年还有1h就过去了

不不不回到正题,这道题嘛~看上去好神啊!

看到此题,我们可以联想到最优比例MST,于是就有了方法:

首先二分答案ans,判断ans是否可行,那如何判断呢?

每条边边权 - ans,之后在新的图中找负环即可。(可以用dfs版的spfa)

 

技术分享
  1 /**************************************************************
  2     Problem: 1486
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:284 ms
  7     Memory:1156 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <cstring>
 12  
 13 using namespace std;
 14 typedef double lf;
 15 const int N = 3005;
 16 const int M = 10005;
 17 const int inf = 1e9;
 18 const lf eps = 1e-10;
 19  
 20 inline int read() {
 21     int x = 0, sgn = 1;
 22     char ch = getchar();
 23     while (ch < 0 || 9 < ch) {
 24         if (ch == -) sgn = -1;
 25         ch = getchar();
 26     }
 27     while (0 <= ch && ch <= 9) {
 28         x = x * 10 + ch - 0;
 29         ch = getchar();
 30     }
 31     return sgn * x;
 32 }
 33  
 34 struct Edge {
 35     int x, y;
 36     lf v;
 37      
 38     inline void Read() {
 39         x = read(), y = read();
 40         scanf("%lf", &v);
 41     }
 42 } E[M];
 43  
 44 struct edge {
 45     int next, to;
 46     lf v;
 47     edge() {}
 48     edge(int _n, int _t, lf _v) : next(_n), to(_t), v(_v) {}
 49 } e[M];
 50  
 51 int n, m;
 52 int first[N], tot;
 53 lf d[N];
 54 bool f, v[N];
 55  
 56 inline void add_edge(int x, int y, lf v) {
 57     e[++tot] = edge(first[x], y, v);
 58     first[x] = tot;
 59 }
 60  
 61 void spfa(int p) {
 62     int x, y;
 63     v[p] = 1;
 64     for (x = first[p]; x; x = e[x].next)
 65         if (d[p] + e[x].v < d[y = e[x].to]) {
 66             if (v[y]) {
 67                 f = 1;
 68                 break;
 69             } else
 70                 d[y] = d[p] + e[x].v, spfa(y);
 71         }
 72     v[p] = 0;
 73 }
 74  
 75 void build_graph(lf x) {
 76     int i;
 77     tot = 0, memset(first, 0, sizeof(first));
 78     for (i = 1; i <= m; ++i)
 79         add_edge(E[i].x, E[i].y, E[i].v - x);
 80 }
 81  
 82 bool check(lf x) {
 83     int i;
 84     build_graph(x);
 85     memset(v, 0, sizeof(v)), memset(d, 0, sizeof(d));
 86     for (i = 1, f = 0; i <= n; ++i) {
 87         spfa(i);
 88         if (f) return 1;
 89     }
 90     return 0;
 91 }
 92  
 93 int main() {
 94     int i;
 95     scanf("%d%d", &n, &m);
 96     for (i = 1; i <= m; ++i)
 97         E[i].Read();
 98     lf l = -inf, r = inf, mid;
 99     while (l + eps < r) {
100         mid = (l + r) / 2;
101         if (check(mid)) r = mid; else l = mid;
102     }
103     printf("%.8lf\n", l);
104     return 0;
105 }
View Code

(p.s.  这就是神奇的叫"分数规划"的东西!!!)

BZOJ1486 [HNOI2009]最小圈

标签:

原文地址:http://www.cnblogs.com/rausen/p/4196757.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!