![[SCOI2014]方伯伯运椰子](/uploads/image/0254.jpg)
嘟嘟嘟
01分数规划思维题。
题中要求交通总量不减少,那么如果总量增加的话,总费用就会增加,所以一定不是更优的解。那么总量守恒。
这是不是就想到了网络流?对于每一个节点流入量等于流出量。然后就是很有思维的一个转化了:把压缩看成退流,把扩容看成增广。
边(x, y)一次压缩,就建一条y -> x,容量为a - d的边。
边(x, y)一次增广,就建一条x -> y,容量为b + d的边。也就是一次调整多出来的费用。那么这样建完图后,图中的一个环就代表一种调整方案!
回头看题,让求某一个比值最小,那一定会想到01分数规划,令ans = max((X - Y) / k),那么ans >= (X - Y) / k,于是有ans * k + Y - X >= 0。按上述的建图,Y - X就是环上的边权和,k就是环中的点数(边数),所以这个式子相当于每经过一条边,这条边的边权就加一个ans,那么ans * k + Y - X >= 0就可以写成Σ(ans + ei) >= 0。二分的时候,如果存在负环,说明mid取小了,向右二分;否则向左二分。
1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<algorithm>
5 #include<cstring>
6 #include<cstdlib>
7 #include<cctype>
8 #include<vector>
9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("")
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 5e3 + 5;
21 const int maxe = 3e3 + 5;
22 inline ll read()
23 {
24 ll ans = 0;
25 char ch = getchar(), last = ' ';
26 while(!isdigit(ch)) {last = ch; ch = getchar();}
27 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
28 if(last == '-') ans = -ans;
29 return ans;
30 }
31 inline void write(ll x)
32 {
33 if(x < 0) x = -x, putchar('-');
34 if(x >= 10) write(x / 10);
35 putchar(x % 10 + '0');
36 }
37
38 int n, m;
39 struct Edge
40 {
41 int nxt, to, w;
42 }e[maxe << 1];
43 int head[maxn], ecnt = -1;
44 void addEdge(int x, int y, int w)
45 {
46 e[++ecnt] = (Edge){head[x], y, w};
47 head[x] = ecnt;
48 }
49
50 db dis[maxn];
51 bool vis[maxn], mak[maxn];
52 bool spfa(int now, db x)
53 {
54 vis[now] = mak[now] = 1;
55 for(int i = head[now]; i != -1; i = e[i].nxt)
56 {
57 if(dis[e[i].to] > dis[now] + e[i].w + x)
58 {
59 dis[e[i].to] = dis[now] + e[i].w + x;
60 if(vis[e[i].to]) return 1;
61 if(spfa(e[i].to, x)) return 1;
62 }
63 }
64 vis[now] = 0;
65 return 0;
66 }
67
68 bool judge(db x)
69 {
70 Mem(vis, 0); Mem(mak, 0);
71 for(int i = 1; i <= n + 2; ++i)
72 if(!mak[i])
73 {
74 if(spfa(i, x)) return 1;
75 }
76 return 0;
77 }
78
79 int main()
80 {
81 Mem(head, -1);
82 n = read(); m = read();
83 for(int i = 1; i <= m; ++i)
84 {
85 int x = read(), y = read(), a = read(), b = read(), c = read(), d = read();
86 if(c) addEdge(y, x, a - d);
87 addEdge(x, y, b + d);
88 }
89 db L = 0, R = 1e5;
90 while(R - L > eps)
91 {
92 db mid = (L + R) / 2.00;
93 if(judge(mid)) L = mid;
94 else R = mid;
95 }
96 printf("%.2lfn", L);
97 return 0;
98 } View Code
转载于:.html
本文发布于:2024-01-31 13:07:59,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170667768028749.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
| 留言与评论(共有 0 条评论) |