P4926 [1007]倍杀测量者
题意:
找到一个最大的T,使得类型1的flag只需要达成SA≥(k−T)∗SB,类型2的flag只需达成SB≥(k+T)∗SA即可不用女装的情况下,仍然有人需要女装。
分析:
使用二分 + 差分约束
首先从题意可知,如果有一个T使得不等式有解,则此时无人女装。同样,如果有一个T使得不等式无解,则此时至少有一个人需要女装。故我们只需要用二分进行枚举并用spfa判负环判断不等式有解还是无解即可。
其次对差分约束系统进行分析:
由于精度问题,我们需要把原式转化为log(SA)≥log(k−T)+log(SB)进行建边即可(另一种类型同理)
所以对于类型1,我们需要从A->B建一条长度为−log(k−T)的边。对于类型2,需要从A->B建一条长度为log(k+T)的边。
此外,对于已知成绩的学生,相当于SC=x等价于SC=x∗S0。经过与上述相同步骤的转化,即可从0到学生C建一条log(x)边,并从学生C到0建一条−log(x)的边。
同时,由于仍有同学可能无法访问,需要建一条从每个同学到源点0的长度为0的边。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| #include <bits/stdc++.h>
using namespace std; #define fast \ ios_base::sync_with_stdio(false); \ cin.tie(NULL); const int N = 1e5 + 10; const int M = 1e6 + 10; const int INF = 0x3f3f3f3f; const long long LINF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-5; struct node { int u, v, next; double w; int type; } a[M]; int f[N], cnt; void add(int u, int v, double w, int type) { a[++cnt].v = v; a[cnt].w = w; a[cnt].type = type; a[cnt].next = f[u]; f[u] = cnt; } int n, s, t; double dis[N]; int sta[N], Count[N], st[N], top = 0; bool spfa(double T){ top = 0; for (int i = 0; i <= n; i++){ dis[i] = 999999999999; Count[i] = 0; st[i] = 0; } dis[0] = 0; queue<int> q; q.push(0); st[0] = 1; while(!q.empty()){ int u = q.front(); q.pop(); st[u] = 0; for (int i = f[u]; i; i = a[i].next){ int v = a[i].v; double w = a[i].w; if(a[i].type == 1) w = -log2(a[i].w - T); if(a[i].type == 2) w = log2(a[i].w + T); if(dis[v] > dis[u] + w){ dis[v] = dis[u] + w; Count[v] = Count[u] + 1; if(Count[v] >= n + 2) return true; if(!st[v]){ st[v] = 1; q.push(v); } } } } return false; } int main() { cin >> n >> s >> t; double l = 0, r = 10; for (int i = 1; i <= n; i++) add(i, 0, 0, 0); for (int i = 1; i <= s; i++){ int type, u, v, w; scanf("%d%d%d%d", &type, &u, &v, &w); add(u, v, (double)w, type); } for (int i = 1; i <= t; i++){ int c, x; scanf("%d%d",&c, &x); add(c, 0, -log2(x), 0); add(0, c, log2(x), 0); } if(!spfa(0)) puts("-1"); else{ double ans = 0; while(fabs(l - r) > eps){ double mid = (l + r) / 2.0; if(spfa(mid)){ ans = mid; l = mid; }else{ r = mid; } } printf("%.6f\n", ans); } return 0; }
|