您的位置:首页 > 其它

BZOJ1486: [HNOI2009]最小圈

2018-03-11 17:25 405 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: