[BZOJ1486][HNOI2009]最小圈
Posted xjr_01
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ1486][HNOI2009]最小圈相关的知识,希望对你有一定的参考价值。
[BZOJ1486][HNOI2009]最小圈
试题描述
输入
见“试题描述”
输出
见“试题描述”
输入示例
4 5 1 2 5 2 3 5 3 1 5 2 4 3 4 1 3
输出示例
3.66666667
数据规模及约定
见“试题描述”
题解
分数规划,二分答案 x 后每条边的边权减去 x,若有负环则表明答案小于等于 x。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <algorithm> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); } return x * f; } #define maxn 3010 #define maxm 10010 #define LL long long int n, m, head[maxn], nxt[maxm], to[maxm]; LL dist[maxm], eval[maxm]; void AddEdge(int a, int b, LL c) { to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m; return ; } LL d[maxn]; bool vis[maxn]; bool spfa(int u) { vis[u] = 1; for(int e = head[u]; e; e = nxt[e]) if(d[to[e]] >= d[u] + eval[e]) { if(vis[to[e]]) return 1; d[to[e]] = d[u] + eval[e]; if(spfa(to[e])) return 1; } vis[u] = 0; return 0; } bool has_ncyc() { memset(vis, 0, sizeof(vis)); memset(d, 0, sizeof(d)); for(int i = 1; i <= n; i++) if(spfa(i)) return 1; return 0; } int main() { LL l = 0, r = 0; n = read(); int M = read(); for(int i = 1; i <= M; i++) { int a = read(), b = read(); LL c = (LL)read() * 2000000000ll; AddEdge(a, b, c); r += c; } l = -r; while(l < r) { LL mid = l + r >> 1; for(int i = 1; i <= m; i++) eval[i] = dist[i] - mid; if(has_ncyc()) r = mid; else l = mid + 1; } printf("%.8lf\n", (double)l / 2e9); return 0; }
以上是关于[BZOJ1486][HNOI2009]最小圈的主要内容,如果未能解决你的问题,请参考以下文章