#差分约束系统,Spfa,SLF优化#HDU 3666 THE MATRIX PROBLEM

题目

多组询问,给定一个\(n*m\)的矩阵\(C\)和一个区间\([L,R]\)
问是否存在一个长度为\(n\)的序列\(A\)和一个长度为\(m\)的序列\(B\)
使得所有

\[\frac{A_i}{B_j}C_{i,j}\in [L,R] \]

不需要输出具体方案


分析

这其实是一个不等式,变量是\(A_i\)\(B_j\),这样可以化简成

\[\frac{L}{C_{i,j}}\leq \frac{A_i}{B_j}\leq \frac{R}{C_{i,j}} \]

这样不够好做,考虑把它化成对数的形式,即是

\[\log(L)-\log(C_{i,j})\leq \log(A_i)-\log(B_j)\leq \log(R)-\log(C_{i,j}) \]

按照这个建图判断有没有负环即可,有负环就是无解
但是bfs版的spfa会TLE,考虑SLF优化,只跑了700ms(但是这样更容易被卡掉)


代码

#include <cstdio>
#include <cctype>
#include <cmath>
#include <deque>
#define rr register
using namespace std;
const int N=811; deque<int>q;
int v[N],cnt[N],as[N],S,n,m,et; double dis[N],l,r;
struct node{int y; double w; int next;}e[N*N>>1];
inline signed iut(){
	rr int ans=0,f=1; rr char c=getchar();
	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans*f;
}
inline void add(int x,int y,double w){
	e[++et]=(node){y,w,as[x]},as[x]=et;
}
inline bool spfa(){
	while (!q.empty()) q.pop_front();
	for (rr int i=1;i<=S;++i)
	    dis[i]=1e18,v[i]=cnt[i]=0;
	q.push_back(S); dis[S]=0,v[S]=1;
	while (!q.empty()){
		rr int x=q.front(); q.pop_front();
		for (rr int i=as[x];i;i=e[i].next)
		if (dis[e[i].y]>dis[x]+e[i].w){
			dis[e[i].y]=dis[x]+e[i].w;
			if (++cnt[e[i].y]>=S) return 0;
			if (!v[e[i].y]){
			    v[e[i].y]=1;
				if (!q.empty()&&dis[e[i].y]<dis[q.front()]) q.push_front(e[i].y);
				    else q.push_back(e[i].y);
		    }
		}
		v[x]=0;
	}
	return 1;
}
signed main(){
	while (scanf("%d",&n)==1){
		m=iut(),S=n+m+1,et=0,
		l=log(iut()),r=log(iut());
		for (rr int i=1;i<=S;++i) as[i]=0;
		for (rr int i=1;i<S;++i) add(S,i,0);
		for (rr int i=1;i<=n;++i)
		for (rr int j=1;j<=m;++j){
			rr double x=log(iut());
			add(i,j+n,r-x),add(j+n,i,x-l);
		}
		puts(spfa()?"YES":"NO");
	}
	return 0;
}
posted @ 2020-12-04 16:09  lemondinosaur  阅读(96)  评论(0编辑  收藏  举报