倍杀测量者 洛谷p4929

题目描述

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

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

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

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

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

输入输出格式

输入格式:

 

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

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

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

 

输出格式:

 

若存在能保证赛后有选手女装的最大的T,则输出T,只有当输出与答案的绝对误差不超过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\leq n\leq5,1\leq s\leq 21≤n≤5,1≤s≤2

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

对于100%的数据,1\leq n,s\leq 1000,1\leq A,B,C,t\leq n,1\leq k\leq 10,1\leq x\leq 10^91≤n,s≤1000,1≤A,B,C,t≤n,1≤k≤10,1≤x≤109。保证输入中的CC两两不同。

本题正解为差分约束


题目大意:有s个关系,第i个为:

Ai\geq≥(Ki-T)Bi \bigvee⋁Ai(Ki+T)>Bi

要你求出最大的T使得其中至少有一个关系不满足

另外有 T\in∈(0,+\propto∝) \bigwedge⋀ \forall∀ki \Rightarrow⇒ki-T\in∈(0,+\propto∝)


我们看差分约束的式子:

如果 a-b\geq≥c

那么就由b向a连一条权值为c的边

最后再跑最长路,看有没有正权环

对于此题的条件来说,我们考虑两边同时取log!!!

那么原条件: Ai\geq≥(Ki-T)Bi \bigvee⋁Ai(Ki+T)>Bi

就可以转化为: log(Ai)\geq≥log(Ki-T)+log(Bi) \bigvee⋁log(Ai)+log(Ki+T)>log(Bi)

再然后: log(Ai)-log(Bi)\geq≥log(Ki-T) \bigvee⋁log(Ai)-log(Bi)>-log(Ki+T)

另外我们观察到k很小,k\in∈[1,10],则T的范围也很小,可以二分T来求解

然后就可以愉快的 二分+差分约束 啦!

再说几个细节:

1.我们注意到可能一些人的分数是已知的,此时我们建一个虚点 n+1

依题意:若有(C,x),则:

addedge(n+1,C,x); addedge(C,n+1,-x)

这是一种差分约束中很经典的维护已知量的方法,它可以确保各个已知点之间的相对关系,其实差分约束维护的就是一个相对关系

2.我们注意到 log(Ai)-log(Bi)>-log(Ki+T)

其实并不满足 a-b\geq≥c的形式,但我们为什么还可以用它呢?

其实题目中有说近似值的事情

因为与真实值相差不超过10^-4即可,所以我们可以做这样的近似

#include<bits/stdc++.h>
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const int MAXN=5005;
int n,s,t;
double dis[MAXN];
int vis[MAXN],tim[MAXN];
struct Edge{
	int v,nxt,flag;
	double w,k;
}e[MAXN<<1];
int h[MAXN],tot;
inline void add(int u,int v,double w,int flag,double k)
{
	e[tot].v=v;
	e[tot].nxt=h[u];
	e[tot].w=w;
	e[tot].flag=flag;
	e[tot].k=k;
	h[u]=tot++;
}
inline bool SPFA(double ans)
{
	int i;
	queue<int> q;
	memset(vis,0,sizeof(vis));
	memset(tim,0,sizeof(tim));
	f(i,1,n+2) dis[i]=-1e9;
//	cout<<dis[1]<<"GG";
	vis[n+2]=1;
	tim[n+2]++;
	dis[n+2]=0;
	q.push(n+2);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(i=h[u];~i;i=e[i].nxt){
			int v=e[i].v;
			double w=e[i].w;
			if(e[i].flag==1) w=log2(e[i].k-ans);
			else if(e[i].flag==2) w=-log2(e[i].k+ans);
			if(dis[v]<dis[u]+w){
				dis[v]=dis[u]+w;
				if(!vis[v]){
					vis[v]=1;
					tim[v]++;
					q.push(v);
					if(tim[v]>n) return false;
				}
			} 
		}
	}
	return true;
}
int main()
{
	ios::sync_with_stdio(false);
	memset(h,-1,sizeof(h));
	int i,j;
	int flag,u,v;
	double x;
	double l=0,r=1000,k;
	cin>>n>>s>>t;
	f(i,1,s){
		cin>>flag>>u>>v>>k;
		add(v,u,0,flag,k);
		if(flag==1)  r=min(r,k);
	}
	f(i,1,t){
		cin>>u>>x;
		add(n+1,u,log2(x),0,0);
		add(u,n+1,-log2(x),0,0);
	}
	f(i,1,n+1){
		add(n+2,i,0,0,0);
	}
	if(SPFA(0)){
		cout<<-1<<endl;
		return 0;
	}
	while(r-l>1e-5){
		double mid=(l+r)/2;
		if(SPFA(mid)) r=mid;
		else l=mid;
	}
	cout<<l<<endl;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值