标签:二分答案,差分约束
题目
题目传送门
题目描述
今天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 1≤n≤5,1≤s≤2
对于另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 1≤n,s≤1000,1≤A,B,C,t≤n,1≤k≤10,1≤x≤109。保证输入中的 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;
}