BZOJ1486: [HNOI2009]最小圈

Posted 嘒彼小星

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1486: [HNOI2009]最小圈相关的知识,希望对你有一定的参考价值。

1486: [HNOI2009]最小圈

Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 2728 Solved: 1315
[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

HINT

Source

题解

\(0/1\)分数规划裸题
学了一发\(dfsspfa\)判负环
依据是任何一个负环都可以从一个点开始走,总是走最短路减小且最短路为负的点到终点
\(d\)全部负为\(0\),就可以保证走的每一步都是负的。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
inline int max(int a, int b){return a > b ? a : b;}
inline int min(int a, int b){return a < b ? a : b;}
inline int abs(int x){return x < 0 ? -x : x;}
inline void swap(int &x, int &y){int tmp = x;x = y;y = tmp;}

inline void read(int &x)
{
    x = 0;char ch = getchar(), c = ch;
    while(ch < '0' || ch > '9') c = ch, ch = getchar();
    while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
    if(c == '-') x = -x;
}
const int INF = 0x3f3f3f3f;
const int MAXN = 3000 + 10;
const int MAXM = 10000 + 10;
const double eps = 0.000000001;
struct Edge
{
    int u,v,nxt;
    double w;
    Edge(int _u, int _v, double _w, int _nxt){u = _u, v = _v, w = _w, nxt = _nxt;}
    Edge(){}
}edge[MAXM << 1];
int head[MAXN], cnt, vis[MAXN], n, m, sum, flag;
double d[MAXN];
inline void insert(int a, int b, double c)
{
    edge[++ cnt] = Edge(a, b, c, head[a]), head[a] = cnt;
}
void dfs(int x)
{
    if(flag) return;
    vis[x] = 1;
    for(int pos = head[x];pos;pos = edge[pos].nxt)
    {
        int v = edge[pos].v;
        if(d[v] > d[x] + edge[pos].w)
        {
            if(vis[v])
            {
                flag = 1;
                break;
            }
            d[v] = d[x] + edge[pos].w;
            dfs(v);
        }
    }
    vis[x] = 0;
}
int main()
{
    read(n), read(m);
    for(int i = 1;i <= m;++ i)
    {
        int tmp1, tmp2;double tmp3;
        read(tmp1), read(tmp2), scanf("%lf", &tmp3);
        insert(tmp1, tmp2, tmp3);
        sum += abs(tmp3);
    }
    double l = -sum, r = sum, mid, ans;
    while(r - l >= eps)
    {
        mid = (l + r) / 2;flag = 0;
        for(int i = 1;i <= cnt;++ i) edge[i].w -= mid;
        for(int i = 1;i <= n;++ i)
        {
            memset(d, 0, sizeof(d));
            dfs(i);
            if(flag) break;
        }
        if(flag) r = mid;
        else l = mid, ans = mid;
        for(int i = 1;i <= cnt;++ i) edge[i].w += mid;
    }
    printf("%.8lf", ans);
    return 0;
}

以上是关于BZOJ1486: [HNOI2009]最小圈的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1486: [HNOI2009]最小圈

BZOJ_1486_[HNOI2009]最小圈_01分数规划

[BZOJ1486][HNOI2009]最小圈

bzoj 1486: [HNOI2009]最小圈

[BZOJ1486][HNOI2009]最小圈

bzoj1486 HNOI2009—最小圈