当前位置: 代码迷 >> 综合 >> 洛谷4926 [1007]倍杀测量者
  详细解决方案

洛谷4926 [1007]倍杀测量者

热度:49   发布时间:2023-12-14 16:21:48.0

标签:二分答案,差分约束

题目

题目传送门

题目描述

今天Scarlet在机房有幸目睹了一场别开生面的OI训练。因为一些奇妙的SPJ,比赛中所有选手的得分都是正实数(甚至没有上限)。

当一位选手A的分数不小于选手B的分数 k k k k > 0 k>0 k>0)倍时,我们称选手A**“ k k k倍杀”了选手B,选手B选手A k k k倍杀”**了

更奇妙也更激动人心的是,训练前有不少选手立下了诸如“我没 k k k倍杀选手X,我就女装”,“选手Y把我 k k k倍杀,我就女装”的Flag。

知道真相的良心教练Patchouli为了维持机房秩序,放宽了选手们的Flag限制。Patchouli设定了一个常数 T T T,立下“我没 k k k倍杀选手X就女装”的选手只要成功 k ? T k-T k?T倍杀了选手X,就不需要女装。同样的,立下“选手Y把我 k k k倍杀我就女装”的选手只要没有成功被选手Y k + T k+T k+T倍杀,也不需要女装。

提前知道了某些选手分数和具体Flag的Scarlet实在不忍心看到这么一次精彩比赛却没人女装,为了方便和Patchouli交易,Scarlet想要确定最大的实数 T T T使得赛后一定有选手收Flag女装。

输入输出格式

输入格式

第一行三个整数 n , s , t n,s,t n,s,t,分别表示机房内选手人数,选手立下的Flag总数和Scarlet已知的选手分数的数量。 n n n位选手从 1 1 1开始编号至 n n n,编号为 k k k的选手被称为选手 k k k

接下来 s s s行,每行四个整数 o , A , B , k o,A,B,k o,A,B,k。其中 o = 1 o=1 o=1表示选手A立下了“我没 k k k倍杀选手B就女装”的Flag, o = 2 o=2 o=2表示选手A立下了“选手B把我 k k k倍杀我就女装”的Flag。

接下来 t t t行,每行两个整数 C , x C,x C,x,表示Scarlet已知选手C的分数为 x x x

输出格式

若存在能保证赛后有选手女装的最大的T,则输出T,只有当输出与答案的绝对误差不超过 1 0 ? 4 10^{-4} 10?4时才被视作正确输出。

若不存在,输出"-1"(去掉引号)

输入输出样例

输入样例#1

3 5 1
1 2 1 2
1 3 2 2
1 3 1 4
2 1 2 2
2 1 3 4
1 1

输出样例#1

-1

输入样例#2

3 2 3
1 2 1 10
2 2 3 6
1 1
2 6
3 9

输出样例#2

3.9999993984

说明

对于30%的数据, 1 ≤ n ≤ 5 , 1 ≤ s ≤ 2 1\leq n\leq5,1\leq s\leq 2 1n5,1s2

对于另40%的数据,保证 t = n t=n t=n

对于100%的数据, 1 ≤ n , s ≤ 1000 , 1 ≤ A , B , C , t ≤ n , 1 ≤ k ≤ 10 , 1 ≤ x ≤ 1 0 9 1\leq n,s\leq 1000,1\leq A,B,C,t\leq n,1\leq k\leq 10,1\leq x\leq 10^9 1n,s1000,1A,B,C,tn,1k10,1x109。保证输入中的 C C C两两不同。

题解

很套路先二分答案

设每个选手的分数为 X i X_i Xi?

为了保证选手A不女装(前提)

如果选手A立下了flag“选手Y把我 k k k倍杀,我就女装”,那么 x A ( k + T ) ≥ x B x_A(k+T)\geq x_B xA?(k+T)xB?

如果选手A立下了flag“我没 k k k倍杀选手X,我就女装”,那么 x A > x B ( k ? T ) x_A>x_B(k-T) xA?>xB?(k?T)

之后可以取log套用差分约束模型

然而我的代码并不是标准的SPFA差分约束模板,但比std快不少(逃

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define mem(x,num) memset(x,num,sizeof x)
#define reg(x) for(int i=last[x];i;i=e[i].next)
#define mid ((l+r)/2)
#define eps 1e-15
#define v e[i].to 
using namespace std;
inline ll read(){
    ll f=1,x=0;char ch=getchar();while(ch<'0'||ch>'9'){
    if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){
    x=x*10+ch-'0';ch=getchar();}return x*f;
}
//**********head by yjjr**********
const int maxn=1e5;
struct node{
    ll o,x,y;double z;}p[maxn];
struct edge{
    int to,next;double w;}e[maxn<<1];
int last[maxn],num=0,cnt=0;bool flag,vis[maxn];
double dis[maxn],b[maxn];ll n,m,s,c,a[maxn];
void insert(int x,int y,double z){
    e[++cnt]=(edge){
    y,last[x],z};last[x]=cnt;}
void dfs(ll x,double k){
    if(vis[x]){
    if(k/dis[x]>eps+1)flag=1;return;}vis[x]=1;dis[x]=k;reg(x){
    dfs(v,k*e[i].w);if(flag)return;}vis[x]=0;
}
int main()
{
    n=read(),m=read(),c=read();rep(i,1,m)p[i]=(node){
    read()-1,read(),read(),read()};s=n+1;rep(i,1,c)a[i]=read(),b[i]=read();bool OK=0;double l=eps,r=10.0-eps;while(num<=100){
    num++;flag=false;mem(last,0);mem(vis,0);mem(dis,0);rep(i,1,c){
    insert(s,a[i],b[i]);insert(a[i],s,1.0/b[i]);}rep(i,1,m)if(!p[i].o)insert(p[i].y,p[i].x,p[i].z-mid);else insert(p[i].y,p[i].x,1.0/(p[i].z+mid));dfs(s,1);if(flag)l=mid,OK=1;else r=mid;}if(OK)printf("%.6lf",l);else puts("-1");return 0;
}
  相关解决方案